Redis鍵空間通知

壹頁書發表於2016-05-25
轉載自:

事件的型別

對於每個修改資料庫的操作,鍵空間通知都會傳送兩種不同型別的事件。

比如說,對 0 號資料庫的鍵 mykey 執行  命令時, 系統將分發兩條訊息, 相當於執行以下兩個  命令:

PUBLISH __keyspace@0__:mykey del
PUBLISH __keyevent@0__:del mykey

訂閱第一個頻道 __keyspace@0__:mykey 可以接收 0 號資料庫中所有修改鍵 mykey 的事件, 而訂閱第二個頻道 __keyevent@0__:del 則可以接收 0 號資料庫中所有執行 del 命令的鍵。

以 keyspace 為字首的頻道被稱為鍵空間通知(key-space notification), 而以 keyevent 為字首的頻道則被稱為鍵事件通知(key-event notification)。

當 del mykey 命令執行時:

  • 鍵空間頻道的訂閱者將接收到被執行的事件的名字,在這個例子中,就是 del 。
  • 鍵事件頻道的訂閱者將接收到被執行事件的鍵的名字,在這個例子中,就是 mykey 。

配置

因為開啟鍵空間通知功能需要消耗一些 CPU , 所以在預設配置下, 該功能處於關閉狀態。

可以透過修改 redis.conf 檔案, 或者直接使用 CONFIG SET 命令來開啟或關閉鍵空間通知功能:

  • 當 notify-keyspace-events 選項的引數為空字串時,功能關閉。
  • 另一方面,當引數不是空字串時,功能開啟。

notify-keyspace-events 的引數可以是以下字元的任意組合, 它指定了伺服器該傳送哪些型別的通知:

字元 傳送的通知
K 鍵空間通知,所有通知以 __keyspace@<db>__ 為字首
E 鍵事件通知,所有通知以 __keyevent@<db>__ 為字首
g DEL 、 EXPIRE 、 RENAME 等型別無關的通用命令的通知
$ 字串命令的通知
l 列表命令的通知
s 集合命令的通知
h 雜湊命令的通知
z 有序集合命令的通知
x 過期事件:每當有過期鍵被刪除時傳送
e 驅逐(evict)事件:每當有鍵因為 maxmemory 政策而被刪除時傳送
A 引數 g$lshzxe 的別名

輸入的引數中至少要有一個 K 或者 E , 否則的話, 不管其餘的引數是什麼, 都不會有任何通知被分發。

舉個例子, 如果只想訂閱鍵空間中和列表相關的通知, 那麼引數就應該設為 Kl , 諸如此類。

將引數設為字串 "AKE" 表示傳送所有型別的通知。

命令產生的通知

以下列表記錄了不同命令所產生的不同通知:

  •  命令為每個被刪除的鍵產生一個 del 通知。
  •  產生兩個通知:為來源鍵(source key)產生一個 rename_from 通知,併為目標鍵(destination key)產生一個 rename_to通知。
  •  和  在鍵被正確設定過期時間時產生一個 expire 通知。當  設定的時間已經過期,或者  傳入的時間為負數值時,鍵被刪除,併產生一個 del 通知。
  •  在命令帶有 STORE 引數時產生一個 sortstore 事件。如果 STORE 指示的用於儲存排序結果的鍵已經存在,那麼程式還會傳送一個 del 事件。
  •  以及它的所有變種( 、  和 )都產生 set 通知。其中  還會產生 expire 通知。
  •  為每個鍵產生一個 set 通知。
  •  產生一個 setrange 通知。
  •  、  、  和  都產生 incrby 通知。
  •  產生 incrbyfloat 通知。
  •  產生 append 通知。
  •  和  都產生單個 lpush 通知,即使有多個輸入元素時,也是如此。
  •  和  都產生單個 rpush 通知,即使有多個輸入元素時,也是如此。
  •  產生 rpop 通知。如果被彈出的元素是列表的最後一個元素,那麼還會產生一個 del 通知。
  •  產生 lpop 通知。如果被彈出的元素是列表的最後一個元素,那麼還會產生一個 del 通知。
  •  產生一個 linsert 通知。
  •  產生一個 lset 通知。
  •  產生一個 ltrim 通知。如果  執行之後,列表鍵被清空,那麼還會產生一個 del 通知。
  •  和  產生一個 rpop 通知,以及一個 lpush 通知。兩個命令都會保證 rpop 的通知在 lpush 的通知之前分發。如果從鍵彈出元素之後,被彈出的列表鍵被清空,那麼還會產生一個 del 通知。
  •  、  和  都只產生一個 hset 通知。
  •  產生一個 hincrby 通知。
  •  產生一個 hincrbyfloat 通知。
  •  產生一個 hdel 通知。如果執行  之後,雜湊鍵被清空,那麼還會產生一個 del 通知。
  •  產生一個 sadd 通知,即使有多個輸入元素時,也是如此。
  •  產生一個 srem 通知,如果執行  之後,集合鍵被清空,那麼還會產生一個 del 通知。
  •  為來源鍵(source key)產生一個 srem 通知,併為目標鍵(destination key)產生一個 sadd 事件。
  •  產生一個 spop 事件。如果執行  之後,集合鍵被清空,那麼還會產生一個 del 通知。
  •  、  和  分別產生 sinterstore 、 sunionostore 和 sdiffstore 三種通知。如果用於儲存結果的鍵已經存在,那麼還會產生一個 del 通知。
  •  產生一個 zincr 通知。(譯註:非對稱,請注意。)
  •  產生一個 zadd 通知,即使有多個輸入元素時,也是如此。
  •  產生一個 zrem 通知,即使有多個輸入元素時,也是如此。如果執行  之後,有序集合鍵被清空,那麼還會產生一個 del通知。
  •  產生一個 zrembyscore 通知。(譯註:非對稱,請注意。)如果用於儲存結果的鍵已經存在,那麼還會產生一個del 通知。
  •  產生一個 zrembyrank 通知。(譯註:非對稱,請注意。)如果用於儲存結果的鍵已經存在,那麼還會產生一個del 通知。
  •  和  分別產生 zinterstore 和 zunionstore 兩種通知。如果用於儲存結果的鍵已經存在,那麼還會產生一個del 通知。
  • 每當一個鍵因為過期而被刪除時,產生一個 expired 通知。
  • 每當一個鍵因為 maxmemory 政策而被刪除以回收記憶體時,產生一個 evicted 通知。

所有命令都只在鍵真的被改動了之後,才會產生通知。

比如說,當  試圖刪除不存在於集合的元素時,刪除操作會執行失敗,因為沒有真正的改動鍵,所以這一操作不會傳送通知。

如果對命令所產生的通知有疑問, 最好還是使用以下命令, 自己來驗證一下:

$ redis-cli config set notify-keyspace-events KEA
$ redis-cli --csv psubscribe '__key*__:*'
Reading messages... (press Ctrl-C to quit)
"psubscribe","__key*__:*",1

然後, 只要在其他終端裡用 Redis 客戶端傳送命令, 就可以看到產生的通知了:

"pmessage","__key*__:*","__keyspace@0__:foo","set" "pmessage","__key*__:*","__keyevent@0__:set","foo" ... 

過期通知的傳送時間

Redis 使用以下兩種方式刪除過期的鍵:

  • 當一個鍵被訪問時,程式會對這個鍵進行檢查,如果鍵已經過期,那麼該鍵將被刪除。
  • 底層系統會在後臺漸進地查詢並刪除那些過期的鍵,從而處理那些已經過期、但是不會被訪問到的鍵。

當過期鍵被以上兩個程式的任意一個發現、 並且將鍵從資料庫中刪除時, Redis 會產生一個 expired 通知。

Redis 並不保證生存時間(TTL)變為 0 的鍵會立即被刪除: 如果程式沒有訪問這個過期鍵, 或者帶有生存時間的鍵非常多的話, 那麼在鍵的生存時間變為 0 , 直到鍵真正被刪除這中間, 可能會有一段比較顯著的時間間隔。

因此, Redis 產生 expired 通知的時間為過期鍵被刪除的時候, 而不是鍵的生存時間變為 0 的時候

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29254281/viewspace-2106922/,如需轉載,請註明出處,否則將追究法律責任。

相關文章