2013-08-20 146 views
10

我們有以下用例:每次某個密鑰過期時,我們需要根據它的值得到通知並執行一些操作。但是,當redis激發expired事件時,當我們稍後嘗試訪問它時,密鑰已經從數據庫中刪除,這當然是期望的。Redis 2.8通知:獲取值而不是密鑰(在到期時)

現在有辦法在失效後再次訪問該條目嗎?我猜不會。

第二種選擇:有沒有辦法告訴redis在發送這些事件時發佈整個值對象而不是發佈密鑰?我想它可以通過Lua添加,但如果可能的話,我會對更簡單的選項感興趣。對於其他事件,我們也需要這種行爲,我們基本上需要所有通知來發布值,而不是密鑰(一旦事件被接收,我們可以做一個GET,但我們想要繞過第二次調用,主要是爲了有一個原子進程,因爲在發佈事件和執行GET以檢索該值之間該值可能已經改變)。

希望這是可以理解的。也許我們看不到明顯的,所以先謝謝了!

+0

到目前爲止,Redis 2.8仍然是候選版本。如果您需要對關鍵過期通知進行控制,則明確實施它可能會更好(不依賴於2.8)。請參閱http://stackoverflow.com/questions/11810020/how-to-handle-session-expire-basing-redis/11815594#11815594 –

+2

那麼,2.8仍然是RC不是問題。問題在於Redis使用密鑰發佈事件,而不是條目的值。而且,因爲我們需要所有通知的這種行爲,所以也是2.6。我們需要一種方式告訴Redis在事件觸發時給我們整個對象,而不是密鑰。 –

+1

我仍然會使用基於zset –

回答

25

Eli鏈接的功能允許您在密鑰過期時收聽。但是,它不會給你鑰匙的價值。此外,基於提交的github問題,它看起來並不像您期望在任何時候即將建立此功能(https://github.com/antirez/redis/issues/1876)。我使用的解決方案是創建一個特殊的「影子」到期密鑰,該密鑰鏈接到您具有實際值的密鑰。

因此可以說你有一個叫做testkey的鍵,它的整數值爲100。此外,密鑰將在10秒後過期,此時您想獲取密鑰的值。 (也許你在10秒內遞增密鑰)。

首先,您需要設置偵聽keyspace事件。特別是你想聽聽expired事件。您可以從您的配置中執行此操作,或在redis中使用config set命令。 (在這裏看到更多的信息:http://redis.io/topics/notifications

CONFIG SET notify-keyspace-events Ex 

現在,您可以訂閱一個特殊的keyevent通道里,你會被通知已過期。

SUBSCRIBE [email protected]__:expired 

要訂閱的頻道格式爲[email protected]<db>__:<eventName>。在我們的例子中,我們假設我們正在使用默認數據庫0,並且我們要監聽expired事件。

testkey到期時,您現在將在__keyevent__通道中收到一條消息,其中消息是過期密鑰的名稱。當然,在這一點上關鍵是消失了,所以我們不能再訪問價值!解決方案是使用特殊的過期密鑰。

當您創建您的testkey時,還會創建一個特殊的過期「影子」鍵(不要過期實際的testkey)。例如:

SET testkey 100 
SET shadowkey:testkey "" EX 10 

現在在[email protected]__:expired通道,你會得到一個消息,告訴您該密鑰shadowkey:testkey過期。取出消息的值(這是密鑰的名稱),分割冒號(或任何您決定使用的分隔符),然後手動獲取密鑰的值並將其刪除。

// set your key value 
SET testkey 100 
//set your "shadow" key, note the value here is irrelevant 
SET shadowkey:testkey "" EX 10 
// Get an expiration message in the channel [email protected]__:expired 
// Split the key on ":", take the second part to get your original key 
// Then get the value and do whatever with it 
GET testkey 
// Then delete the key 
DEL testkey 

注意,shadowkey的值沒有使用,所以你要使用它根據這個答案(Redis store key without a value)的最小可能值是一個空字符串""。這是一個更多的工作來設置,但上述系統完全符合您的需求。開銷是一些額外的命令,用於實際檢索和刪除密鑰以及空密鑰的存儲成本。

+0

不錯的主意,雖然它的值增加了一倍。可能的調整隻是將值存儲在「影子」鍵中,並使用實際的鍵僅用於到期目的。 –

+1

@ItamarHaber shadowkey不存儲實際值。事實上,基於這個答案(http://stackoverflow.com/questions/25557250/redis-store-key-without-value)陰影鍵值應該只是一個空字符串(在我的例子中,我給了它一個值「1」但現在已更新)。所以唯一的開銷是一個額外的鑰匙(你不應該複製你的價值) – Sarus

+0

正確的 - 讀它倒過來:) –

1

如果你在2.8,你可以嘗試this new feature(也引用在this page)。這肯定是不穩定的,似乎沒有很好的測試,但如果你在2.8反正...

從發行短期介紹:

在數據庫中的一個有趣的功能,以鍵值數據模型(Redis 並不完全符合此定義,因爲這些值是複雜的數據結構,但Redis的外層肯定是關鍵值 業務)是以某種方式訂閱針對某個事件的事件的能力給定的關鍵。

比如我可能有興趣看到當鑰匙FOO被刪除或修改以某種方式 ,或與 把所有的按鍵的名稱到期設置(使用EXPIRE命令)的Redis從驅逐 數據集,因爲他們的生存時間降爲零。

Redis用戶羣多次要求此功能,但是到目前爲止我們還沒有達到建議的API(包括我自己提出的 提議)似乎很適合Redis設計的程度。 此功能請求將嘗試描述一個新設計,該設計非常易於使用,實施,並且非常適合Redis 故事。