Redis发布与订阅(pub/sub)
Redis發(fā)布與訂閱(pub/sub)
本文檔翻譯自:?http://redis.io/topics/pubsub?。
SUBSCRIBE?、?UNSUBSCRIBE?和?PUBLISH?三個命令實現(xiàn)了發(fā)布與訂閱信息泛型(Publish/Subscribe messaging paradigm), 在這個實現(xiàn)中, 發(fā)送者(發(fā)送信息的客戶端)不是將信息直接發(fā)送給特定的接收者(接收信息的客戶端), 而是將信息發(fā)送給頻道(channel), 然后由頻道將信息轉(zhuǎn)發(fā)給所有對這個頻道感興趣的訂閱者。
發(fā)送者無須知道任何關(guān)于訂閱者的信息, 而訂閱者也無須知道是那個客戶端給它發(fā)送信息, 它只要關(guān)注自己感興趣的頻道即可。
對發(fā)布者和訂閱者進(jìn)行解構(gòu)(decoupling), 可以極大地提高系統(tǒng)的擴(kuò)展性(scalability), 并得到一個更動態(tài)的網(wǎng)絡(luò)拓?fù)?#xff08;network topology)。
比如說, 要訂閱頻道?foo?和?bar?, 客戶端可以使用頻道名字作為參數(shù)來調(diào)用?SUBSCRIBE?命令:
redis> SUBSCRIBE foo bar當(dāng)有客戶端發(fā)送信息到這些頻道時, Redis 會將傳入的信息推送到所有訂閱這些頻道的客戶端里面。
正在訂閱頻道的客戶端不應(yīng)該發(fā)送除?SUBSCRIBE?和?UNSUBSCRIBE?之外的其他命令。 其中,?SUBSCRIBE?可以用于訂閱更多頻道, 而?UNSUBSCRIBE?則可以用于退訂已訂閱的一個或多個頻道。
SUBSCRIBE?和?UNSUBSCRIBE?的執(zhí)行結(jié)果會以信息的形式返回, 客戶端可以通過分析所接收信息的第一個元素, 從而判斷所收到的內(nèi)容是一條真正的信息, 還是?SUBSCRIBE?或?UNSUBSCRIBE?命令的操作結(jié)果。
信息的格式
頻道轉(zhuǎn)發(fā)的每條信息都是一條帶有三個元素的多條批量回復(fù)(multi-bulk reply)。
信息的第一個元素標(biāo)識了信息的類型:
- subscribe?: 表示當(dāng)前客戶端成功地訂閱了信息第二個元素所指示的頻道。 而信息的第三個元素則記錄了目前客戶端已訂閱頻道的總數(shù)。
- unsubscribe?: 表示當(dāng)前客戶端成功地退訂了信息第二個元素所指示的頻道。 信息的第三個元素記錄了客戶端目前仍在訂閱的頻道數(shù)量。 當(dāng)客戶端訂閱的頻道數(shù)量降為?0?時, 客戶端不再訂閱任何頻道, 它可以像往常一樣, 執(zhí)行任何 Redis 命令。
- message?: 表示這條信息是由某個客戶端執(zhí)行?PUBLISH?命令所發(fā)送的, 真正的信息。 信息的第二個元素是信息來源的頻道, 而第三個元素則是信息的內(nèi)容。
舉個例子, 如果客戶端執(zhí)行以下命令:
redis> SUBSCRIBE first second那么它將收到以下回復(fù):
1) "subscribe" 2) "first" 3) (integer) 11) "subscribe" 2) "second" 3) (integer) 2如果在這時, 另一個客戶端執(zhí)行以下?PUBLISH?命令:
redis> PUBLISH second Hello那么之前訂閱了?second?頻道的客戶端將收到以下信息:
1) "message" 2) "second" 3) "hello"當(dāng)訂閱者決定退訂所有頻道時, 它可以執(zhí)行一個無參數(shù)的?UNSUBSCRIBE?命令:
redis> UNSUBSCRIBE這個命令將接到以下回復(fù):
1) "unsubscribe" 2) "second" 3) (integer) 11) "unsubscribe" 2) "first" 3) (integer) 0訂閱模式
Redis 的發(fā)布與訂閱實現(xiàn)支持模式匹配(pattern matching): 客戶端可以訂閱一個帶?*?號的模式, 如果某個/某些頻道的名字和這個模式匹配, 那么當(dāng)有信息發(fā)送給這個/這些頻道的時候, 客戶端也會收到這個/這些頻道的信息。
比如說,執(zhí)行命令
redis> PSUBSCRIBE news.*的客戶端將收到來自?news.art.figurative?、?news.music.jazz?等頻道的信息。
客戶端訂閱的模式里面可以包含多個 glob 風(fēng)格的通配符, 比如?*?、???和?[...]?, 等等。
執(zhí)行命令
redis> PUNSUBSCRIBE news.*將退訂?news.*?模式, 其他已訂閱的模式不會被影響。
通過訂閱模式接收到的信息, 和通過訂閱頻道接收到的信息, 這兩者的格式不太一樣:
- 通過訂閱模式而接收到的信息的類型為?pmessage?: 這代表有某個客戶端通過?PUBLISH?向某個頻道發(fā)送了信息, 而這個頻道剛好匹配了當(dāng)前客戶端所訂閱的某個模式。 信息的第二個元素記錄了被匹配的模式, 第三個元素記錄了被匹配的頻道的名字, 最后一個元素則記錄了信息的實際內(nèi)容。
客戶端處理?PSUBSCRIBE?和?PUNSUBSCRIBE?返回值的方式, 和客戶端處理?SUBSCRIBE?和?UNSUBSCRIBE?的方式類似: 通過對信息的第一個元素進(jìn)行分析, 客戶端可以判斷接收到的信息是一個真正的信息, 還是?PSUBSCRIBE?或?PUNSUBSCRIBE?命令的返回值。
通過頻道和模式接收同一條信息
如果客戶端訂閱的多個模式匹配了同一個頻道, 或者客戶端同時訂閱了某個頻道、以及匹配這個頻道的某個模式, 那么它可能會多次接收到同一條信息。
舉個例子, 如果客戶端執(zhí)行了以下命令:
SUBSCRIBE foo PSUBSCRIBE f*那么當(dāng)有信息發(fā)送到頻道?foo?時, 客戶端將收到兩條信息: 一條來自頻道?foo?,信息類型為?message?; 另一條來自模式?f*?,信息類型為?pmessage?。
訂閱總數(shù)
在執(zhí)行?SUBSCRIBE?、?UNSUBSCRIBE?、?PSUBSCRIBE?和?PUNSUBSCRIBE?命令時, 返回結(jié)果的最后一個元素是客戶端目前仍在訂閱的頻道和模式總數(shù)。
當(dāng)客戶端退訂所有頻道和模式, 也即是這個總數(shù)值下降為?0?的時候, 客戶端將退出訂閱與發(fā)布狀態(tài)。
編程示例
Pieter Noordhuis 提供了一個使用 EventMachine 和 Redis 編寫的?高性能多用戶網(wǎng)頁聊天軟件?, 這個軟件很好地展示了發(fā)布與訂閱功能的用法。
客戶端庫實現(xiàn)提示
因為所有接收到的信息都會包含一個信息來源:
- 當(dāng)信息來自頻道時,來源是某個頻道;
- 當(dāng)信息來自模式時,來源是某個模式。
因此, 客戶端可以用一個哈希表, 將特定來源和處理該來源的回調(diào)函數(shù)關(guān)聯(lián)起來。 當(dāng)有新信息到達(dá)時, 程序就可以根據(jù)信息的來源, 在 O(1) 復(fù)雜度內(nèi), 將信息交給正確的回調(diào)函數(shù)來處理。
from:?http://redisdoc.com/topic/pubsub.html
總結(jié)
以上是生活随笔為你收集整理的Redis发布与订阅(pub/sub)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Redis通信协议(protocol)
- 下一篇: Redis复制(Replication)