2015-11-14 33 views
0

我在rails項目中緩存方法的結果有問題。Rails.cache在不同的線程中沒有緩存?

我來到這個代碼,模擬兩種不同的要求:

[ 
    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 { sleep(1); puts Rails.cache.fetch('a', expires_in: 2.seconds) { rand } }, 
    Thread.new { puts Rails.cache.fetch('a', expires_in: 2.seconds) { rand } } 
] 

回答

1

在代碼的第一塊

[ 
    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應用程序中的文件夾/ 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」是在高速緩存文件已經。所以這就是它工作的原因。

讓再拍模擬,而不是使用「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 } } 
] 

它可以作爲我們的預期,以及!

+0

謝謝總管Hieu。我想你是對的。 – kajamite

0

你可以使用互斥體,防止在同一時間運行的一些代碼:

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 } } } ] 
相關問題