redis 發布和訂閱實現

2022-08-19 00:12:18 字數 2771 閱讀 9371

參考文獻

15天玩轉redis —— 第九篇 發布/訂閱模式

《redis設計與實現》

psubscribe

publish

pubsub

punsubscribe

subscribe

unsubscribe

接下來一一簡述下這個6個命令的相關使用。

subscribe channel [channel ...]

訂閱給定的乙個或多個頻道的資訊。

subscribe命令可以訂閱乙個頻道。當有任何乙個客戶端向這個頻道推送訊息的時候,訂閱了這個頻道的客戶端都可以收到資料。

如上所述,客戶端可以訂閱乙個頻道的訊息,那麼我是否可以訂閱滿足一定條件的頻道的所有訊息呢?redis提供了psubscribe命令,這個命令可以訂閱符合模式的頻道的訊息。每個模式以 * 作為匹配符,比如 it* 匹配所有以 it 開頭的頻道( it.news 、 it.blog 、 it.tweets 等等), news.* 匹配所有以 news. 開頭的頻道( news.it 、 news.global.today 等等),諸如此類。

psubscribe pattern [pattern ...]
我訂閱了乙個頻道,也有需求退訂。unsubscribe命令就提供了客戶端退訂乙個渠道的功能。

unsubscribe [channel [channel ...]]
同理,如果我通過某個模式訂閱了頻道,我今天有點小後悔想退訂這個模式咋辦?使用punsubscribe命令就可以達成這個功能。

publish命令可以向乙個頻道推送訊息。如上面說到的,如果使用publish命令向乙個頻道推送訊息,則所有訂閱了這個頻道的客戶端都可以收到這個訊息。

publish channel message
上面都是關於訂閱和退訂相關的功能的簡述。如果我是管理redis的乙個dba,需要檢視當前有多少個活躍的頻道(活躍頻道指的是那些至少有乙個訂閱者的頻道),每個頻道有多少的訂閱者,有多少模式訂閱的相關資訊怎麼辦呢?redis給我們提供了pubsub命令。

pubsub [argument [argument ...]]
pubsub channels [pattern]:列出當前的活躍頻道。活躍頻道指的是那些至少有乙個訂閱者的頻道,訂閱模式的客戶端不計算在內。

pattern 引數是可選的:

如果不給出 pattern 引數,那麼列出訂閱與發布系統中的所有活躍頻道。

如果給出 pattern 引數,那麼只列出和給定模式 pattern 相匹配的那些活躍頻道。

pubsub numsub [channel-1 ... channel-n] : 返回給定頻道的訂閱者數量,訂閱模式的客戶端不計算在內。

pubsub numpat : 返回訂閱模式的數量。注意,這個命令返回的不是訂閱模式的客戶端的數量,而是客戶端訂閱的所有模式的數量總和。

前面的篇幅主要介紹了redis提供的發布和訂閱功能,接下來將介紹下發布和訂閱功能具體是怎麼實現的。

當你在redis客戶端鍵入subscribe的時候,就會建立乙個客戶端與乙個頻道的訂閱關係。那麼redis是通過怎樣的形式來完成這個關聯的呢?在redis中,將所有的頻道和客戶端的訂閱關係都儲存在乙個叫puhsub_channels的字典中。這個字典的key是是某個頻道,而values則是乙個鍊錶,記錄了所有訂閱這個頻道的客戶端。

struct redisserver
因此當建立乙個客戶端和頻道的訂閱關係的時候,大體會經歷如下的兩步操作:

如果該頻道已經存在於pubsub_channels中,則將客戶端加到這個鍊錶的後面。

如果這個頻道不存在,則在字典中建立乙個新的頻道,然後將客戶端新增到鍊錶中。

退訂的操作則和訂閱的操作相反:

根據退訂的頻道是哪個,將鍊錶上對應的客戶端刪除。

如果刪除了客戶端之後,整個鍊錶為空,則表示這個頻道沒有被訂閱,因此這個頻道也將被刪除 。

前面的部分說到了一般的訂閱和退訂,接下來將介紹redis模式的訂閱是如何實現的。在redis中所有的模式的訂閱的關係都儲存在伺服器的pubsub_patterns 屬性中。這個屬性是乙個鍊錶結構。

struct redisserver
鍊錶結構中每乙個節點都包含了乙個pubsub_pattern 結構。

typedef struct pubsubpattern pubsubpattern;
當客戶端執行模式的訂閱命令的時候,伺服器會執行以下的幾個操作:

新建乙個pubsubpattern,將結構的pattern設定為被訂閱的模式,client設定為訂閱這個模式的客戶端。

然後將這個結構體掛到pubsub_patterns的尾部。

退訂的操作則剛好相反:

遍歷pubsub_pattern,找到客戶端退訂的模式,將這個鍊錶的節點刪除

如前面的章節所述,頻道的訂閱是通過pubsub_channels結構實現的。那麼當推送乙個訊息給頻道的訂閱者的時候,則需要執行如下的幾個操作:

根據頻道的名稱在dict pubsub_channels中找到對應的頻道

遍歷這個頻道上所有的訂閱者名單,將資訊挨個傳送給訂閱者

那麼模式的訂閱的訊息傳送是如何實現的呢?其實實現的原理就更簡單了,redis會遍歷pubsub_patterns上所有的鍊錶節點,找到匹配的模式,然後傳送訊息。

Redis 發布和訂閱

發布與訂閱 又稱pub sub 訂閱者 listener 負責訂閱頻道 channel 傳送者 publisher 負責向頻道傳送二進位制字串訊息 binary string message 每當有訊息被傳送給指定頻道的時候,頻道都所有訂閱者都會收到訊息。redis提供都5個發布訂閱命令 命令描述 ...

Redis 發布和訂閱

一 概述 1 發布和訂閱是一種訊息通訊模式。2 優點 使訊息訂閱者和訊息發布者耦合度降低,類似設計模式中的觀察者模式。二 發布和訂閱 訂閱命令 訂閱乙個或多個頻道 返回值 value 1 為 subcribe 表示訂閱成功,value 2 為訂閱的頻道名稱,value 3 表示當前訂閱的頻道個數 s...

Java實現Redis發布訂閱

jedis使用指南 簡介 redis提供了基於 發布 訂閱 模式的訊息機制,此種模式下,訊息發布者和訂閱者不進行直接通訊,發布者客戶端向指定的頻道 channel 發布訊息,訂閱該頻道的每個客戶端都可以收到該訊息 頻道沒有 建立 的概念,可以直接訂閱 亦可直接發布訊息 下圖展示了頻道 channel...