《Redis官方文件》釋出和訂閱
原文連結:
釋出/訂閱(Pub/Sub)
SUBSCRIBE、UNSUBSCRIBE 和 PUBLISH 這三個命令實現了釋出/訂閱訊息模式(引用自維基百科),傳送者(釋出者)並不是直接傳送它們的訊息給指定的接收者(訂閱者),而是將訊息釋出到特定的訊息通道,並且不需要知道訂閱者(如果有的話)的任何資訊。訂閱者可以訂閱一個或多個感興趣的訊息通道,同時也只會收到他們感興趣通道的資訊,而不用去關心是誰釋出的。這種釋出者與訂閱者的解耦,使其具備更強的擴充套件性並得到一個更加動態的網路拓撲。
例如為了訂閱通道foo和bar,客戶端可以使用通道名稱為引數去呼叫 SUBSCRIBE 命令:
SUBSCRIBE foo bar
其他客戶端傳送到訊息到這些通道時,訊息會由 Redis 推送到所有訂閱了這些通道的客戶端。
訂閱了一個或多個通道的客戶端就不應該再使用命令,儘管它還能訂閱其他頻道或取消訂閱其他通道。訂閱和取消訂閱的執行結果會以訊息的形式返回。所以客戶端能夠解析這互相耦合的訊息,其中第一個元素表示訊息的型別。訂閱了通道的客戶端上允許使用的命令有 SUBSCRIBE、PSUBSCRIBE、UNSUBSCRIBE、PUNSUBSCRIBE、PING和QUIT。
推送訊息的格式
訊息是一條含有三個元素的@array-reply。第一個元素是訊息的型別:
- subscribe:意味著我們已經成功訂閱了第二個元素所指的通道。第三個引數表示當前已經訂閱的通道總數。
- unsubscribe:意味著已經成功的取消了第二個元素所指的通道。第三個引數表示當前訂閱的頻道總數。當最後一個引數是 0 的時候,就表示不再訂閱任何頻道,同時客戶端也可以使用Redis提供的任何命令,因為此時客戶端已經退出釋出/訂閱狀態。
- message:這是某一個客戶端使用 PUBLISH 命令後會收到的操作結果資訊。第二個元素是資訊來源的頻道,同時第三個引數是真實訊息的內容。
資料庫與範圍
Pub/Sub 模式與 KEY 空間無關。它與任何層面無關,包括資料庫數目。
在 db 10 上進行釋出,db 1上的訂閱者也會收到資訊。
如果你需要覆蓋某一些型別,把頻道的字首用一些特定的變數(test,staging,production….)
例如:
SUBSCRIBE first second *3 $9 subscribe $5 first :1 *3 $9 subscribe $6 second :2
此時,從另一個客戶端上對 second 頻道執行 PUBLISH 命令操作:
PUBLISH second Hello
這就是前面訂閱了頻道的客戶端收到的資訊:
*3 $7 message $6 second $5 Hello
現在客戶端執行無參的 UNSUBSCRIBE 命令來取消自己訂閱的所有頻道:
UNSUBSCRIBE *3 $11 unsubscribe $6 second :1 *3 $11 unsubscribe $5 first :0
訂閱的模式匹配
Redis 的 Pub/Sub 實現支援模式匹配。客戶端可以用 glob 風格的模式去接收頻道名稱與模式相匹配的所有頻道訊息。
例如:執行命令PSUBSCRIBE news.*的客戶端將後收到所有傳送到 news.art.figurative,news.music.jazz 等等頻道的資訊。所有 glob 風格的模式匹配都是有效的,同時也支援多重萬用字元。
執行命令PUNSUBSCRIBE news.*的客戶端會取消訂閱頻道名稱與 給定模式(news.*) 相匹配的所有頻道,而其他已經訂閱的頻道不會愛影響。模式匹配訂閱的資訊格式是另一種不同的格式:
訊息的型別是 pmessage:表示另一個客戶端執行 PUBLISH 命令向頻道傳送訊息,而頻道符合當前客戶端訂閱的模式匹配。第二個元素就是匹配的模式,第三個元素就是模式匹配到的頻道名稱,最後一個元素就是真正的訊息載體。
與系統處理 SUBSCRIBE 和 UNSUBSCRIBE, PSUBSCRIBE 和 PUNSUBSCRIBE 命令一樣,傳送的訊息型別為 psubscribe 和 punsubscribe ,然後使用 subscribe 和 unsubscribe 一樣的訊息格式。
訊息同時匹配模式與訂閱的頻道
一個客戶端可能多次收到同一條訊息,如果它訂閱的多個模式匹配到了一條釋出的訊息,或者它訂閱的模式與頻道匹配到了同一條訊息。例如:
SUBSCRIBE foo PSUBSCRIBE f*
在上面的例子中,如果一條訊息傳送到foo頻道,客戶端將會收到兩條訊息。一個是 message型別的訊息,一種是pmessage型別的訊息。
模式匹配下訂閱數的意義
在 subscribe, unsubscribe, psubscribe 和 punsubscribe 等訊息型別中,最後一個引數表示仍在訂閱的頻道數。這個數字實際上就是客戶端訂閱的頻道與模式的總數。
所以當客戶端取消訂閱所有頻道和模式時,也就是這個總數值變為 0 時,客戶端將會退出 Pub/Sub 模式。
程式設計示例
Pieter Noordhuis 提供了一個很好的例子,通過 EventMachine 和 Redis建立了一個多使用者高效能的WEB聊天網站。
客戶端庫實現提示
由於所有的訊息都會有一個訂閱源。(當訊息型別為 message 時,訂閱源是一個頻道,當訊息型別為 pmessage 時,訂閱源是一個模式)客戶端可以利用一個HASH表將這些訂閱源與回撥函式繫結起來,這樣當一個訊息被接收後,能在 O(1) 的時間內將訊息交給註冊好的回撥函式。
二進位制的蛇
YY-JAVA研發工程師熱愛技術、熱愛分享、熱愛交流
輕度強迫症、完美主義
Git:https://github.com/Json-Liu