Rails.cache在不同的线程中没有缓存?
我在rails项目中遇到缓存方法结果的问题。
我来到这个模拟两个不同请求的代码:
[ Thread.new { puts Rails.cache.fetch('a', expires_in: 2.seconds) { rand } }, Thread.new { puts Rails.cache.fetch('a', expires_in: 2.seconds) { rand } } ]
尝试在rails控制台中执行它。 如果我尝试在控制台中作为输出运行它,我得到不同的数字。 怎么可能?
但是例如这段代码(带睡眠)按预期工作:
[ Thread.new { sleep(1); puts Rails.cache.fetch('a', expires_in: 2.seconds) { rand } }, Thread.new { puts Rails.cache.fetch('a', expires_in: 2.seconds) { rand } } ]
在第一块代码中
[ Thread.new { puts Rails.cache.fetch('a', expires_in: 2.seconds) { rand } }, Thread.new { puts Rails.cache.fetch('a', expires_in: 2.seconds) { rand } } ]
我认为您的rails配置正在使用文件进行缓存(为了确保这一点,请检查rails应用程序中的文件夹/ tmp / cache)。
因为’Rails.cache’需要从文件中执行读取缓存,所以它非常耗时,并且2个线程中的’fetch’操作大多数同时运行,因此’a’值不存在或已经过期。
在第二块代码中
[ Thread.new { sleep(1); puts Rails.cache.fetch('a', expires_in: 2.seconds) { rand } }, Thread.new { puts Rails.cache.fetch('a', expires_in: 2.seconds) { rand } } ]
当第一个线程尝试获取’a’时,’a’已经在缓存文件中。 这就是为什么它有效。
让我们进行另一次模拟,而不是使用’Rails.cache’,我们将使用这样的MemoryStore缓存:
cache = ActiveSupport::Cache::MemoryStore.new(expires_in: 5.minutes) [ Thread.new { puts cache.fetch('a', expires_in: 2.seconds) { rand } }, Thread.new { puts cache.fetch('a', expires_in: 2.seconds) { rand } } ]
它也符合我们的期望!
您可以使用互斥锁来防止同时运行某些代码:
mutex = Mutex.new [ Thread.new { puts mutex.synchronize { Rails.cache.fetch('a', expires_in: 2.seconds) { rand } } }, Thread.new { puts mutex.synchronize { Rails.cache.fetch('a', expires_in: 2.seconds) { rand } } } ]