標籤:redis publish subscribe 發布訂閱 channel
在上一篇中我們寫了Redis的任務隊列。
除了實現任務隊列外,Redis還提供了一組命令可以讓開發人員實現“發布/訂閱”(publish/subscribe)模式。“發布/訂閱”模式同樣可以實現進程間的訊息傳遞,其原理是這樣的:
“發布/訂閱”模式中包含兩種角色,分別是發行者和訂閱者。訂閱者可以訂閱一個或若干個頻道(channel),而發行者可以向指定的頻道發送訊息,所有訂閱此頻道的訂閱者都會收到此訊息。
發行者發布訊息的命令是PUBLISH,用法是PUBLISH channel message,如向channel.1說一聲“hi”:
redis><span style="font-size:14px;">PUBLISH channel</span>.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個值,第一個值是訊息的類型,根據訊息類型的不同,第二、三個值的含義也不同。訊息類型可能的取值有:
(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 …]],如果不指定頻道則會取消訂閱所有頻道。
按照規則訂閱
除了可以使用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,但不會匹配channel.。這時在執行個體B中發布訊息:
redis B>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研究(十六)—發布/訂閱模式