2017-04-12 22 views
10

我使用Rails 5.我currenlty使用Rails內存緩存緩存數據庫查詢結果,例如,這是我state.rb模型...如何創建第二個Rails內存存儲緩存?

def self.cached_find_by_iso_and_country_id(iso, country_id) 
    if iso 
     Rails.cache.fetch("#{iso.strip.upcase} #{country_id}") do 
     find_by_iso_and_country_id(iso.strip.upcase, country_id) 
     end 
    end 
    end 

我的問題是,如何能我創建了第二個內存中的Rails緩存(我需要一個用於存儲從互聯網上下載的文件),這不會干擾我上面的查詢緩存?我不希望我的文件緩存中的條目導致我的查詢緩存中的條目被驅逐。

+0

只需使用不同的密鑰? –

+0

是的,但如果我使用不同的密鑰,現在沒有競爭的條目在單個緩存中嗎?我不希望我的密鑰存儲文件驅逐用於存儲查詢的LRU條目...也許我不理解緩存。 – Dave

回答

7

是的,你可以用Rails來做到這一點。您需要創建第二個緩存並將其作爲全局變量提供給您的應用程序,然後根據上下文調用適當的緩存。每個緩存都分配有自己的內存塊(默認爲32 MB),如果一個緩存填滿,則不會影響其他緩存。這是通過ActiveSupport::Cache::MemoryStore.new完成的。

我將證明,兩個緩存不會影響對方:

首先,生成將被用來測試緩存兩個文本文件,一個10 MB和一個30 MB:

dd if=/dev/zero of=10M bs=1m count=10 
dd if=/dev/zero of=30M bs=1m count=30 

打開一個Rails控制檯,並閱讀這些成字符串:

ten = File.read("10M"); 0 
thirty = File.read("30M"); 0 

商店ten在緩存:

Rails.cache.fetch("ten") { ten }; 0 

確認的數據緩存:

Rails.cache.fetch("ten")[0..10] 
=> "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" 

商店thirty在緩存:

Rails.cache.fetch("thirty") { thirty }; 0 

確認沒有被保存(過大在緩存中保存的時候作爲一個字符串展開) :

Rails.cache.fetch("thirty")[0..10] 
NoMethodError: undefined method `[]' for nil:NilClass 

確認這已經破壞了整個緩存:

Rails.cache.fetch("ten")[0..10] 
NoMethodError: undefined method `[]' for nil:NilClass 

現在創建第二個高速緩存並確認其行爲與原始緩存:

store = ActiveSupport::Cache::MemoryStore.new 
store.fetch("ten") { ten }; 0 
store.fetch("ten")[0..10] 
=> "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" 
store.fetch("thirty") { thirty }; 0 
store.fetch("thirty")[0..10] 
NoMethodError: undefined method `[]' for nil:NilClass 
store.fetch("ten")[0..10] 
NoMethodError: undefined method `[]' for nil:NilClass 

現在有兩個空的緩存:storeRails.cache。讓我們確認他們是獨立的:

Rails.cache.fetch("ten") { ten }; 0 
Rails.cache.fetch("ten")[0..10] 
=> "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" 
store.fetch("thirty") { thirty }; 0 # bust the `store' cache 
Rails.cache.fetch("ten")[0..10] 
=> "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" 

如果那麼這兩個緩存干擾最後store.fetch電話會打掉兩個高速緩存。它只是破壞store

要實現第二個高速緩存在您的應用程序,創建一個初始化config/initializers/cache.rb並添加:

$cache = ActiveSupport::Cache::MemoryStore.new 

調用新的緩存在你的代碼,你會Rails.cache以同樣的方式:

$cache.fetch("foo") { "bar" } 

一些這些細節取自this answer。新的緩存支持更多選項;有關定製緩存的更多信息,請檢查MemoryStoreCaching with Rails

該解決方案適用於小型應用程序。注意從MemoryStore文檔此評論:

如果你正在運行on Rails的服務器進程多個Ruby(這是如果你使用mongrel_cluster或乘客的Phusion的情況下),那麼這意味着Rails的服務器進程實例贏得無法互相共享緩存數據,這可能不是該場景中最合適的緩存。

+0

我準備回答這個問題時正要回答這個問題。看到你已經做到了。很好的解釋! –