1. 程式人生 > >Redis研究(十六)—釋出/訂閱模式

Redis研究(十六)—釋出/訂閱模式

        在上一篇中我們寫了Redis的任務佇列。

        除了實現任務佇列外,Redis還提供了一組命令可以讓開發者實現“釋出/訂閱”(publish/subscribe)模式。“釋出/訂閱”模式同樣可以實現程序間的訊息傳遞,其原理是這樣的:

        “釋出/訂閱”模式中包含兩種角色,分別是釋出者和訂閱者。訂閱者可以訂閱一個或若干個頻道(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.1
Reading 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.*才能退訂