带Memcache的Rails返回错误的缓存对象?

我有一个相当大的Rails应用程序,它在单独的服务器上使用memcached作为其缓存存储。

问题是我在生产环境中随机获取错误,这似乎表明memcached返回了一个不正确的对象。

例子:

在此示例中, current_site是一个帮助方法,它访问Site模型上使用Rails.cache缓存模型的方法

 ActionView::TemplateError in ListingsController#edit undefined method `settings' for # On line #12 of app/views/layouts/site.html.erb 9:  10:  11: 12:  13: <meta name="verify-v1" content="" /> 14:  15: 

与…形成对比

 ActionView::TemplateError in ApplicationController#not_found undefined method `settings' for # On line #12 of app/views/layouts/site.html.erb 9:  10:  11: 12:  13: <meta name="verify-v1" content="" /> 14:  15: 

两者都应该返回Site模型!

另一个缓存行为的例子很奇怪:

 ActionView::TemplateError in AccountsController#show can't convert Category into String On line #141 of app/views/layouts/site.html.erb 138: <li> 139:  140:  141:  142: 
    :slugs).each_with_index do |top_level_page, i| %> 143: <li> 144:

有没有人遇到过这样的事情? 任何人都有关于诊断这个无法解决的问题的想法!? 我已经尝试切换出memcached客户端gem,想想也许这是一个奇怪的错误,但这没有任何影响! 谢谢。

这是由Passenger共享其与Memcached服务器的连接引起的。 查看http://www.modrails.com/documentation/Users%20guide.html#_example_1_memcached_connection_sharing_harmful 。

修复只是将Passenger’s Rails的产生改为conservative

一些可能会有所帮助的事情:

  • 将检测/日志记录添加到current_site以查看确切返回的内容。
  • 你如何在memcache中指定密钥? 您可能会意外地在两个不同的位置为两个不同的对象使用相同的密钥。
  • 使用memcached-tool host:port dump > /tmp/keys来查看memcache中的实际内容。
  • 你的memcached是在防火墙后面而不是暴露在公共IP上,对吧?

我也遇到了这个问题,并且解决了在缓存提供程序进行解组操作之前为每个类/模型添加require_dependency。 也许在生产环境中这不是必需的,因为选项:config.cache_class设置为true,但在测试和开发中它是错误的。

实际上,Memcache(我正在使用的缓存提供程序)找不到引用的类来执行unmarshal然后引发此错误。

在这篇文章中有一个更好的解决方案来解决这个问题: http : //kballcodes.com/2009/09/05/rails-memcached-a-better-solution-to-the-undefined-classmodule-problem/

问候!

是的,我已经发生了这种情况。 对我来说,这是因为我正在做Rails.cache.fetch(key)并且密钥是空白的。

我已经在Rails控制台中做了一些游戏,并使用以下内容:

 Rails.cache.read validkey # Get back the proper data Rails.cache.fetch('') { 'abc' } # Error in rails log: 'MemCacheError ():' Rails.cache.read validkey # Get back nil Rails.cache.read validkey # May get back proper data 

如果其他人出现,则添加评论…… kballcodes.comurl不再有效(尽管您仍然可以通过archive.org访问它)。 在该博客文章的评论中,有人描述了一种方法,使Marshal尝试加载有问题的对象,如果它首先抛出’undefined class / module’错误。 我在下面包含了该代码,并在代码示例下引用了原作者。

将其添加到RAILS_ROOT / config / initializers /文件夹中的初始化文件中:

 # # Marshal.load is a C-method built into Ruby; because it's so low-level, it # bypasses the full classloading chain in Ruby, in particular the #const_missing # hook that Rails uses to auto-load classes as they're referenced. This monkey # patch catches the generated exceptions, parses the message to determine the # offending constant name, loads the constant, and tries again. # # This solution is adapted from here: # http://kballcodes.com/2009/09/05/rails-memcached-a-better-solution-to-the-undefined-classmodule-problem/ # class < e if e.message =~ %r(undefined class/module) const = e.message.split(' ').last const.constantize retry else raise(e) end end end alias_method_chain :load, :rails_classloader end 

所有这一切归功于马特·布朗 ( Matt Brown) ,他将这段代码作为一个牧师,并评论了上面现已发表的文章: