《Redis的鍵空間通知詳解》要點:
本文介紹了Redis的鍵空間通知詳解,希望對您有用。如果有疑問,可以聯(lián)系我們。
重要: 鍵空間通知(Keyspace Notification)是一個從Redis 2.8.0版本開始可用的功能.
一、功能概述
鍵空間通知使得客戶端能夠訂閱Pub/Sub(發(fā)布/訂閱)頻道,這樣客戶端便能接收到以某種方式影響Redis數(shù)據(jù)集的事件.
可能接收到的事件示例,如下所示:
所有影響到一個給定鍵的命令.
所有接收到一個LPUSH命令的鍵.
所有數(shù)據(jù)庫-0中的鍵全都過期.
Redis會使用標(biāo)準(zhǔn)的Pub/Sub層來傳遞事件,因此,實現(xiàn)了Pub/Sub功能的客戶端能夠直接使用這個功能,而不用進行任何修改.
因為Redis的Pub/Sub功能當(dāng)前是“觸發(fā)后不管(Fire and Forget)”的,所以如果你的應(yīng)用程序?qū)κ录兄?strong>可靠通知的要求,那么它就不能使用Redis的鍵空間通知功能.也便是說,如果你的Pub/Sub客戶端斷開連接,然后再重新連接,那么在客戶端斷開連接的期間內(nèi)傳遞的所有事件都會丟失.
Redis將來會改善事件傳遞的可靠性,但是很有可能會以一種更加常規(guī)的方式來辦理這個問題,有可能會提高Pub/Sub功能自身的可靠性,也有可能會通過Lua腳本攔截Pub/Sub消息,然后再執(zhí)行某些操作(例如,將事件存入一個列表之中).
二、事件類型
每次執(zhí)行會影響到Redis數(shù)據(jù)空間的操作時,鍵空間通知就會發(fā)送兩個不同類型的事件.以DEL操作為例,當(dāng)刪除數(shù)據(jù)庫-0
中的一個名為mykey
的鍵時,將會觸發(fā)Redis傳遞兩條消息,完全等價于下面兩條PUBLISH命令:
PUBLISH __keyspace@0__:mykey del
PUBLISH __keyevent@0__:del mykey
很容易看出,如何讓一個頻道能夠監(jiān)聽mykey
鍵相關(guān)的所有事件,以及如何讓另一個頻道能夠獲取del
操作所影響的所有的鍵的有關(guān)信息.
第一種類型的事件,頻道名稱的前綴為keyspace
,這種事件被稱為鍵空間通知;而第二種類型的事件,頻道名稱的前綴為keyevent
,這種事件被稱為鍵事件通知.
在上面的示例中,Redis會針對mykey
鍵產(chǎn)生一個del
事件.期間發(fā)生的事情,如下所示:
鍵空間頻道會接收到一條消息,它的內(nèi)容是事件名稱.
鍵事件頻道會接收到一條消息,它的內(nèi)容是鍵的名稱.
為了使Redis只傳遞我們感興趣的事件子集,因此只可以使用一種類型的通知.
三、配置辦法
在默認情況下,鍵空間的事件通知功能是禁用的,因為這個功能會消耗一些CPU性能,雖然幾乎感覺不到性能消耗.有兩種辦法可以啟用通知功能:修改redis.conf文件的notify-keyspace-events
參數(shù),或者使用CONFIG SET命令.
將上述參數(shù)設(shè)置為空字符串,就能禁用通知功能.如果想要啟用這個功能,那么就要將上述參數(shù)設(shè)置為一個空字符串,這個字符串由多個字符組成,其中的每個字符都具有特殊含義,如下表所示:
字符 | 含義 |
---|---|
K | 鍵空間(Keyspace)事件,通過__keyspace@<db>__ 前綴的頻道發(fā)布. |
E | 鍵事件(Keyevent)事件,通過__keyevent@<db>__ 前綴的頻道發(fā)布. |
g | 通用的命令(不特定類型),例如:DEL、EXPIRE、RENAME,等等. |
$ | 字符串(String)相關(guān)的命令. |
l | 列表(List)相關(guān)的命令. |
s | 集合(Set)相關(guān)的命令. |
h | 哈希(Hash)相關(guān)的命令. |
z | 有序集合相關(guān)的命令. |
x | 過期事件(每當(dāng)一個鍵過期時,便會產(chǎn)生這種事件). |
e | 內(nèi)存回收事件(當(dāng)達到最大內(nèi)存,然后回收某個鍵的內(nèi)存時,便會產(chǎn)生這種事件). |
A | g$lshzxe的別名.因此,“AKE”字符串可以表示所有的事件. |
配置字符串至少應(yīng)當(dāng)包括K
或E
字符.否則,即使這個字符串包括其他任何字符,Redis也不會傳遞任何事件.
例如,若只想針對列表(List)啟用鍵空間事件,則配置參數(shù)必需設(shè)置為Kl
,以此類推.
KEA
字符串可用于啟用每種可能的事件.
四、不同命令產(chǎn)生的事件
不同的命令會產(chǎn)生不同類型的事件,如以下列表所示:
DEL
這個命令會為每個被刪除的鍵產(chǎn)生一個del
事件.
RENAME
這個命令會產(chǎn)生兩個事件,一個為原始鍵產(chǎn)生的rename_from
事件,以及一個為目標(biāo)鍵產(chǎn)生的rename_to
事件.
EXPIRE
當(dāng)為某個鍵設(shè)置過期時間時,這個命令便會產(chǎn)生一個expire
事件;或者,每當(dāng)為某個待刪除的鍵設(shè)置一個過期結(jié)果時,這個命令便會產(chǎn)生一個expired
事件(請參考EXPIRE命令的相關(guān)文檔).
SORT
當(dāng)使用STORE
選項來設(shè)置一個新鍵時,這個命令便會產(chǎn)生一個sortstore
事件.如果結(jié)果列表為空,并且使用了STORE
選項,并且已經(jīng)存在一個同名的鍵,那么Redis便會刪除這個已有的鍵,在這種情況下,這個命令還會產(chǎn)生一個del
事件.
SET
這個命令,以及它的所有變種(SETEX、SETNX、GETSET)命令,都會產(chǎn)生set
事件.除此之外,SETEX命令還會產(chǎn)生一個expire
事件.
MSET
這個命令會為每個鍵單獨產(chǎn)生一個set
事件.
SETRANGE
這個命令會產(chǎn)生一個setrange
事件.
INCR、DECR、INCRBY、DECRBY
這些命令都會產(chǎn)生incrby
事件.
INCRBYFLOAT
這個命令會產(chǎn)生一個incrbyfloat
事件.
APPEND
這個命令會產(chǎn)生一個append
事件.
LPUSH、LPUSHX
這些命令都會產(chǎn)生一個lpush
事件,即使有多個輸入元素時,也是如此.
RPUSH、RPUSHX
這些命令都會產(chǎn)生一個rpush
事件,即使有多個輸入元素時,也是如此.
RPOP
這個命令會產(chǎn)生一個rpop
事件.另外,如果從列表中彈出最后一個元素,那么這個列表對應(yīng)的鍵就會被刪除,此時還會產(chǎn)生一個del
事件.
LPOP
這個命令會產(chǎn)生一個lpop
事件.另外,如果從列表中彈出最后一個元素,那么這個列表對應(yīng)的鍵就會被刪除,此時還會產(chǎn)生一個del
事件.
LINSERT
這個命令會產(chǎn)生一個linsert
事件.
LSET
這個命令會產(chǎn)生一個lset
事件.
LREM
這個命令會產(chǎn)生一個lrem
事件.另外,如果運行這個命令之后,列表變?yōu)榭毡?那么便會刪除這個列表對應(yīng)的鍵,此時還會產(chǎn)生一個del
事件.
LTRIM
這個命令會產(chǎn)生一個ltrim
事件.另外,如果運行這個命令之后,列表變?yōu)榭毡?那么便會刪除這個列表對應(yīng)的鍵,此時還會產(chǎn)生一個del
事件.
RPOPLPUSH、BRPOPLPUSH
這兩個命令都會產(chǎn)生一個rpop
事件和lpush
事件.這兩個事件的產(chǎn)生順序都是固定不變的,先產(chǎn)生rpop
事件,然后再產(chǎn)生lpush
事件.另外,如果運行這兩個命令之后,列表變?yōu)榭毡?那么便會刪除這個列表對應(yīng)的鍵,此時還會產(chǎn)生一個del
事件.
HSET、HSETNX、HMSET
這些命令都會產(chǎn)生一個hset
事件.
HINCRBY
這個命令會產(chǎn)生一個hincrby
事件.
HINCRBYFLOAT
這個命令會產(chǎn)生一個hincrbyfloat
事件.
HDEL
這個命令會產(chǎn)生一個hdel
事件.如果運行這個命令之后,哈希變?yōu)榭?那么便會刪除這個哈希對應(yīng)的鍵,此時還會產(chǎn)生一個del
事件.
SADD
這個命令會產(chǎn)生一個sadd
事件,即使有多個輸入元素時,也是如此.
SREM
這個命令會產(chǎn)生一個srem
事件.如果運行這個命令之后,集合變?yōu)榭?那么便會刪除這個集合對應(yīng)的鍵,此時還會產(chǎn)生一個del
事件.
SMOVE
這個命令會為原始鍵產(chǎn)生一個srem
事件,然后為目標(biāo)鍵產(chǎn)生一個sadd
事件.
SPOP
這個命令會產(chǎn)生一個spop
事件.如果運行這個命令之后,集合變?yōu)榭?那么便會刪除這個集合對應(yīng)的鍵,此時還會產(chǎn)生一個del
事件.
SINTERSTORE、SUNIONSTORE、SDIFFSTORE
這些命令會分別產(chǎn)生sinterstore
、sunionostore
和sdiffstore
事件.在特殊情況下,如果運行這些命令得到的集合為空,并且用于存儲結(jié)果的鍵已經(jīng)存在,那么這個鍵將會被刪除,然后還會產(chǎn)生一個del
事件.
ZINCRBY
這個命令會產(chǎn)生一個zincr
事件.
ZADD
這個命令會產(chǎn)生一個zadd
事件,即使有多個輸入元素時,也是如此.
ZREM
這個命令會產(chǎn)生一個zrem
事件,即使必要刪除多個元素時,也是如此.如果運行這個命令之后,有序集合變?yōu)榭?那么便會刪除這個有序集合對應(yīng)的鍵,此時還會產(chǎn)生一個del
事件.
ZREMRANGEBYSCORE
這個命令會產(chǎn)生一個zrembyscore
事件.如果運行這個命令之后,有序集合變?yōu)榭?那么便會刪除這個有序集合對應(yīng)的鍵,此時還會產(chǎn)生一個del
事件.
ZREMRANGEBYRANK
這個命令會產(chǎn)生一個zrembyrank
事件.如果運行這個命令之后,有序集合變?yōu)榭?那么便會刪除這個有序集合對應(yīng)的鍵,此時還會產(chǎn)生一個del
事件.
ZINTERSTORE、ZUNIONSTORE
這兩個命令會分別產(chǎn)生zinterstore
和zunionstore
事件.在特殊情況下,如果運行這些命令得到的有序集合為空,并且用于存儲結(jié)果的鍵已經(jīng)存在,那么這個鍵將會被刪除,然后還會產(chǎn)生一個del
事件.
每當(dāng)一個鍵因為過期而被刪除時,便會產(chǎn)生一個expired
事件.
每當(dāng)一個鍵因為maxmemory
策略而被刪除,以便于回收內(nèi)存時,便會產(chǎn)生一個evicted
事件.
重要: 所有的命令只有當(dāng)目標(biāo)鍵真的被修改時,才會產(chǎn)生事件.例如,當(dāng)使用SREM命令刪除一個集合中并不存在的元素時,實際上沒有改變這個鍵的對應(yīng)值,所以也就不會產(chǎn)生任何事件.
如果還在懷疑一個給定命令的事件是如何產(chǎn)生的,那么最簡單的辦法便是自己驗證一下.在Shell終端中運行以下命令:
redis-cli config set notify-keyspace-events KEA
redis-cli --csv psubscribe '__key*__:*'
此時,Redis客戶端便進入頻道監(jiān)聽狀態(tài),如下圖所示:
此時,在另一個Shell終端中使用redis-cli
命令向Redis服務(wù)器發(fā)送命令:
redis-cli set foo hello
然后,便能在前一個Shell終端中觀察到以下輸出信息:
五、過期事件的產(chǎn)生時機
Redis會通過以下兩種方式使得具有生存時間的鍵過期:
當(dāng)使用某個命令拜訪這個鍵,然后發(fā)現(xiàn)這個鍵已經(jīng)過期.
通過一個后臺系統(tǒng)在后臺漸進地查找已經(jīng)過期的鍵,這樣還能夠收集從未被拜訪過的鍵.
當(dāng)通過上述兩種方式之一拜訪某個鍵,并且發(fā)現(xiàn)這個鍵已經(jīng)過期時,Redis就會產(chǎn)生expired
事件.結(jié)論便是,Redis服務(wù)器并不能保證每當(dāng)鍵的生存時間降低至0的時候就能立刻產(chǎn)生expired
事件.
如果總是沒有任何命令拜訪這個已經(jīng)過期的鍵,并且?guī)в猩鏁r間(TTL:Time To Live)的鍵非常多的話,那么就很有可能感覺到鍵的生存時間降低至0和產(chǎn)生expired
事件之間具有明顯的延時.
基本上,只有當(dāng)Redis服務(wù)器刪除已經(jīng)過期的鍵時才會產(chǎn)生expired
事件,而不是當(dāng)鍵的生存時間在理論上降低至0的時候.
六、鍵空間通知示例
接下來,會通過實際操作,簡單講解Redis鍵空間通知的使用辦法.
1. 安裝Redis
依照《在CentOS上安裝Redis緩存系統(tǒng)》安裝Redis服務(wù)器.
2. 啟用鍵空間通知功能
在Shell終端(此處取名為終端-1)中運行以下命令,進入Redis客戶端的命令行:
redis-cli
然后在終端-1的Redis客戶端的命令行中運行以下命令,啟用鍵空間通知功能的所有通知:
config set notify-keyspace-events KEA
3. 訂閱鍵空間通知和鍵事件通知
打開一個新的Shell終端(此處取名為終端-2),在其中運行以下命令,進入telnet命令行:
telnet localhost 6379
在終端-2的telnet命令行中,運行以下命令:
psubscribe __key*__:*
上述命令會訂閱鍵空間通知和鍵事件通知,當(dāng)對某個鍵執(zhí)行修改命令時,終端-2便會同時收到上述兩種通知.
4. 設(shè)置鍵的值
在終端-1的Redis客戶端的命令行中運行以下命令,設(shè)置一個鍵的值:
set mykey hello
5. 觀察結(jié)果
此時,便能在終端-2觀察到兩條通知消息,如下圖所示:
上圖的上半部分就是鍵空間通知,下半部分就是鍵事件通知.
《Redis的鍵空間通知詳解》是否對您有啟發(fā),歡迎查看更多與《Redis的鍵空間通知詳解》相關(guān)教程,學(xué)精學(xué)透。維易PHP學(xué)院為您提供精彩教程。
轉(zhuǎn)載請注明本頁網(wǎng)址:
http://www.snjht.com/jiaocheng/10659.html