2016-07-06 127 views
3

我想了解使用Rails.cache.fetch時Rails中的race_condition_ttl指令。瞭解Rails中的race_condition_ttl

我有一個控制器的動作,看起來像這樣:

def foo 
    @foo = Rails.cache.fetch("foo-testing", expires_in: 30.seconds, race_condition_ttl: 60.seconds) do 
     Time.now.to_s 
    end 
    @foo # this gets used in a view down the line... 
end 

基於什麼我讀了Rails的文檔,此值應在30秒後到期,但陳舊的值允許服務再過60秒。但是,我無法弄清楚如何重現那些能夠讓我看到這種行爲有效的條件。這是我試圖測試它的方式。

100.times.map do 
    t = Thread.new { RestClient.get("http://myenvironment/foo") } 
    t 
end.map {|t| t.join.value }.uniq 

我有我的Rails應用程序在標準nginx /獨角獸設置後面的虛擬機上運行。我試圖同時產生100個線程同時模擬「狗樁效應」。但是,當我運行我的測試代碼時,所有線程都返回相同的值。我期望看到的是一個線程得到了新的價值,而另一個線程得到了一些陳舊的內容。

任何指針都歡迎!非常感謝。

+1

試試'Time.now.to_f'或'SecureRandom.uuid'。默認情況下'Time.now.to_s'只准確到一秒鐘,所以很可能,即使它確實不同,你也不會注意到,因爲它穩定得這麼快。 – tadman

+0

@tadman謝謝,讓我試試。 – bitops

+1

@tadman通過使用更精細的值,我確實看到了一些差異。我會看看這個主題中的其他答案,看看我能否獲得更多的理解。謝謝! – bitops

回答

2

您正在將race_condition_ttl設置爲60秒,這意味着您的線程只會在此時間過期後纔開始獲取新值,即使不考慮最初的30秒。

您的測試看起來不會花1.5分鐘來運行,這是線程開始獲取新值所需的。從Rails Cache docs

是的,這個過程是延長陳舊值的時間再過幾秒鐘。由於前一個緩存的使用壽命延長,其他進程將繼續稍微使用稍陳舊的數據。

本文意味着使用一個小的race_condition_ttl,它的目的和測試都是有意義的。

UPDATE

還要注意的是,只有當它最近已過期失效的高速緩存的壽命得以延長。否則會生成一個新值,並且:race_condition_ttl不起任何作用。

沒有閱讀源不是特別清楚時,其服務器酩酊大醉或什麼的Rails如何決定究竟recently指在上述報價。但似乎很清楚,等待訪問緩存的第一個進程(很多)會在延長前一個進程的壽命的同時設置新值。等待進程的存在可能是Rails尋找的條件。在任何情況下,在初始超時和ttl到期並且緩存開始提供更新的值之後,應該觀察到預期的行爲。初始超時與新值開始顯示的時間之間的延遲應與ttl類似。當然,前提條件是服務器應該在初始超時到期的時候受到攻擊。

+0

感謝您的回答!我讀這意味着緩存必須不斷讀取,爲了ttl踢了嗎?意思是說,如果高速緩存在30秒後變得陳舊,然後我刷新了,那麼ttl沒有理由進入?但是如果服務器持續受到打擊,那麼ttl會被應用?對不起,如果不清楚。 – bitops

+1

我同意那個閱讀。請參閱我的答案更新。 –