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 } } } ]