標籤:
Redis 提供了一組命令可以讓開發人員實現 “發布/訂閱” 模式。“發布/訂閱” 可以實現進程間的訊息傳遞,其原理是這樣的:
“發布/訂閱” 模式中包含兩種角色,分別是發行者和訂閱者。訂閱者可以訂閱一個或若干個頻道(channel),而發行者可以向指定的頻道發送訊息,所有訂閱此頻道的訂閱者都會收到此訊息。
發行者發布訊息的命令是 PUBLISH,用法是 PUBLISH channel message,如向 channel.1 說一聲 “hi”:
redis> PUBLISH channel.1 hi(integer) 0
這樣訊息就發出去了。PUBLISH 命令的傳回值表示接收到這條訊息的訂閱者數量。因為此時沒有客訂閱 channel.1,所以返回 0。發出去的訊息不會被持久化,也就是說當有客訂閱 channel.1 後只能收到後續發布到該頻道的訊息,之前發送的就收不到了。
訂閱頻道的命令是 SUBSCRIBE,可以同時訂閱多個頻道,用法是 SUBSCRIBE channel [channel ...]。現在新開一個 redis-cli 執行個體 A,用它來訂閱 channel.1:
redis A> SUBSCRIBE channel.1Reading messages... (press Ctrl-C to quit)1) "subscribe"2) "channel.1"3) (integer) 1
執行 SUBSCRIBE 命令後用戶端會進入訂閱狀態,處於此狀態下用戶端不能使用除 SUBSCRIBE、UNSUBSCRIBE、PSUBSCRIBE 和 PUNSUBSCRIBE 這 4 個屬於 “發布/訂閱” 模式的命令之外的命令,否則會報錯。
進入訂閱狀態後用戶端可能收到 3 種類型的回複。每種類型的回複都包含 3 個值,第一個值是訊息的類型,根據訊息類型不同,第二、三個值的含義也不同。訊息類型可能的取值有以下 3 個。
(1)subscribe。表示訂閱成功的反饋資訊。第二個值是訂閱成功的頻道名稱,第三個值是當前客訂閱的頻道數量。
(2)message。表示接收到的訊息。第二個值表示產生訊息的頻道名稱,第三個值是訊息的內容。
(3)unsubscribe。表示成功取消訂閱某個頻道。第二個值是對應的頻道名稱,第三個值是當前客訂閱的頻道數量,當次值為 0 時用戶端會退出訂閱狀態,之後就可以執行其他非 “發布/訂閱” 模式的命令了。
上例中當執行個體 A 訂閱了 channel.1 進入訂閱狀態後收到了一條 subscribe 類型的回複,這時我們開啟另一 redis-cli 執行個體 B,並向 channel.1 發送一條訊息:
redis B> PUBLISH channel.1 hi!(integer) 1
傳回值為 1,表示有一個客訂閱了 channel.1,此時執行個體 A 收到了類型為 message 的回複:
1) "message"2) "channel.1"3) "hi!"
使用 UNSUBSCRIBE 命令可以取消指定的頻道,用法為 UNSUBSCRIBE [channel [channel ...]],如果不指定頻道則會取消訂閱所有頻道。由於 redis-cli 的限制,無法在其中測試 UNSUBSCRIBE 命令。
按照規則訂閱
除了可以使用 SUBSCRIBE 命令訂閱指定名稱的頻道外,還可以使用 PSUBSCRIBE 命令訂閱指定的規則。規則支援 glob 風格萬用字元格式,下面新開啟一個 redis-cli 執行個體 C 進行示範:
redis C> PSUBSCRIBE channel.?*Reading messages... (press Ctrl-C to quit)1) "psubscribe"2) "channel.?*"3) (integer) 1
規則 channel.?* 可以匹配 channel.1 和 channel.10,但不會匹配 channel1.。這時在執行個體 B 中發布訊息:
127.0.0.1:6379> PUBLISH channel.1 hi!(integer) 2
返回結果為 2 是因為執行個體 A 和執行個體 C 兩個用戶端都訂閱了 channel.1 頻道。執行個體 C 接收到的回複是:
1) "pmessage"2) "channel.?*"3) "channel.1"4) "hi!"
第一個值表示這條訊息是通過 PSUBSCRIBE 命令訂閱頻道而收到的,第二個值表示訂閱時使用的萬用字元,第三個值表示實際收到訊息的頻道命令,第三個值則是訊息內容。
使用 PSUBSCRIBE 命令可以重複訂閱一個頻道,如某用戶端執行 PSUBSCRIBE channel.? channel.?*,這時想 channel.2 發布訊息後該用戶端會收到兩條訊息,而同時 PUBLISH 命令返回的值也是 2 而不是 1。同樣的,如果有另一用戶端執行了 SUBSCRIBE channel 10 和 PSUBSCRIBE channel.?* 的話,向 channel.10 發送命令該用戶端也會收到兩條訊息(但是是兩種類型:message 和 pmessage),同時 PUBLISH 命令會返回 2。
PUNSUBSCRIBE 命令可以退訂指定的規則,用法是 PUNSUBSCRIBE [pattern [pattern ...]],如果沒有參數則會退訂所有規則。
使用 PUNSUBSCRIBE 命令只能退訂通過 PSUBSCRIBE 命令訂閱的規則,不會影響直接通過 SUBSCRIBE 命令訂閱的頻道;同樣 UNSUBSCRIBE 命令也不會影響通過 PSUBSCRIBE 命令訂閱的規則。另外容易出錯的一點是使用 PUNSUBSCRIBE 命令退訂某個規則時不會將其中的萬用字元展開,而是進行嚴格的字串匹配,所以 PUNSUBSCRIBE * 無法退訂 channel.* 規則,而是必須使用 PUNSUBSCRIBE channel.* 才能退訂。
Redis - 發布/訂閱模式