摘要:的發布訂閱功能由等命令組成。發布與訂閱頻道名中國男籃戰勝了美國男籃,獲得了奧運冠軍訂閱多個頻道則直接添加該數組子元素這里除了這條命令之外其它命令都不能使用留意我們接收消息的回調函數。那么將消息發送給模式的訂閱者。
Redis的發布訂閱功能由 PUBLISH、SUBSCRIBE、PSUBSCRIBE等命令組成。
通過執行SUBSCRIBE命令,客戶端可以訂閱一個或多個頻道從而成為這些頻道的訂閱者(subscriber),
當有其它客戶端向被訂閱的頻道發送消息時,頻道的所有訂閱者都能收到這條消息。
在下圖中客戶端A、客戶端B、客戶端C,分別訂閱了cctv.5這個頻道。這個時候某個客戶端執行了如下這條命令:
PUBLICH "cctv.5" "中國男籃戰勝了美國男籃,獲得了奧運冠軍"
此時訂閱了cctv.5這個頻道的所有客戶端都將收到這條消息。
除了訂閱頻道之外,客戶端還可以通過執行PSUBSCRIBE命令訂閱一個或多個模式,從而成為這些模式的訂閱者。每當有其他客戶端向某個頻道發送消息時,消息不僅僅會發送給這個頻道的訂閱者,還會發送給與這個頻道相匹配的模式訂閱者。
上圖中,我們給cctv.3這個頻道發送了一條消息"同一首歌",該消息首先會發送給它的訂閱者client A,然后根據模式匹配,cctv.3符合cctv.*這個模式。所以訂閱了cctv.*頻道的訂閱者也都可以收到消息呢。(●′?`●)?
頻道的訂閱
當一個客戶端執行SUBSCRIBE命令訂閱某個或某些頻道的時候,這個客戶端與被訂閱頻道之間就建立了一種訂閱關系。
Redis 將所有頻道的訂閱關系都保存在服務器狀態的pubsub_channels字典里面,這個字典的鍵是某個被訂閱的頻道,值是一個鏈表,鏈表里面記錄了所有訂閱這個頻道的客戶端。
客戶端執行SUBSCRIBE命令訂閱某個或某些頻道的時候,服務器都會將客戶端與被訂閱的頻道在 pubsub_channels 字典中進行關聯。
根據頻道是否已經有其他訂閱者,關聯操作分為兩種情況執行:
頻道已經有其他訂閱者,那么在pubsub_channels字典中必然有相應的訂閱者鏈表。程序唯一要做的是將客戶端添加到鏈表的末尾。
頻道沒有其它訂閱者,程序首先要在pubsub_channels字典中為頻道創建一個鍵,并將值設置為空鏈表,然后將客戶端添加到鏈表。成為鏈表的第一個元素。
php 發布與訂閱demo
// publish.php connect("127.0.0.1",6379); // 頻道名 $channel = "cctv.5"; $message = "中國男籃戰勝了美國男籃,獲得了奧運冠軍"; $Redis->publish($channel,$message); ?> // subscribe.php connect("127.0.0.1",6379); $channel = ["cctv.5"]; // 訂閱多個頻道則直接添加該數組子元素 $Redis->subscribe($channel,function($instance,$channel,$message){ // 這里除了SUBSCRIBE、PSUBSCRIBE、UNSUBSCRIBE、PUNSUBSCRIBE這4條命令之外其它命令都不能使用 var_dump($instance,$channel,$message); }); ?>留意我們接收消息的回調函數。除了SUBSCRIBE、PSUBSCRIBE、UNSUBSCRIBE、PUNSUBSCRIBE這4條命令以外,其它命令都不能使用。
如果你使用的是CLI(命令行界面)此處是有bug的,你可能無法退訂消息。只能通過組合鍵Ctrl+c結束退訂。
退訂頻道
使用UNSUBSCRIBE命令可以退訂某個或某些頻道。服務器將從pubsub_channels中解除客戶端與被退訂頻道之間的關聯:
程序會根據被退訂頻道的名字、在pubsub_channels字典中找到頻道對應的訂閱者鏈表,然后從訂閱者鏈表中刪除退訂客戶端的信息。
如果刪除了客戶端之后,頻道的訂閱者鏈表變成了空鏈表,那么說明這個頻道已經沒有任何的訂閱者了,程序將從pubsub_channels字典中刪除頻道對應的鍵。
訂閱模式
服務器將所有的訂閱關系都保存在服務器狀態的pubsub_channels屬性里面,在模式訂閱里服務器也將所有模式的訂閱關系都保存在服務器狀態的pubsub_patterns屬性里面。
struct redisServer { // ... // 保存所有模式訂閱關系 list *pubsub_patterns; // ... }
pubsub_patterns 屬性是一個鏈表,鏈表中的每個節點都包含著一個pubsubPattern結構,這個結構的pattern屬性記錄了被訂閱的模式,而client屬性則記錄了訂閱模式的客戶端。
typedef struct pubsubPattern { // 訂閱模式的客戶端 redisClient *client; // 被訂閱的模式 robj * pattern; } pubsubPattern;
每當客戶端執行PSUBSCRIBE命令訂閱某個或某些模式的時候,服務器會對每個被訂閱的模式執行以下兩個操作:
新建一個pubsubPattern結構,將結構的pattern屬性設置為被訂閱的模式(如:music.*),client 屬性設置為訂閱模式的客戶端。
將pubsubPattern結構添加到pubsub_patterns鏈表的表尾。
退訂模式
模式的退訂命令PUNSUBSCRIBE是PSUBSCRIBE命令的反操作。當一個客戶端退訂某個或某些模式的時候,服務器將在pubsub_patterns鏈表中查找并刪除那些pattern屬性為退訂模式并且client屬性為執行退訂命令的客戶端的pubsubPattern結構。
發送消息
redis客戶端執行 PUBLISH
將消息發送給頻道的所有訂閱者。
如果有一個或多個模式與頻道相匹配。那么將消息發送給pattern模式的訂閱者。
第一個操作的偽代碼:
def channel_publish(channel,message): /* 如果channel鍵不存在pubsub_channels字典中 那么說明channel頻道沒有任何訂閱者 程序不做發送動作直接返回 */ if channel not in server.pubsub_channels: return /* 運行到這里,說明channel頻道至少有一個訂閱者 程序將遍歷channel頻道的訂閱者列表 將消息發送給所有訂閱者 */ for subscriber in server.pubsub_channels[channel]: send_message(subscriber,message)
第二個操作,因為服務器狀態中的pubsub_patterns鏈表記錄了所有模式的訂閱關系,所以為了將消息發送給所有與channel頻道相匹配的模式的訂閱者,PUBLISH命令要做的就是遍歷整個pubsub_patterns鏈表,查找那些模式相匹配的訂閱者。
def pattern_publish(channel,message): # 遍歷所有模式訂閱消息 for pubsubPattern in server.pubsub_patterns: # 如果頻道和模式相匹配 if(match(channel,pubsubPatter.pattern)): # 那么將消息發送給訂閱該模式的客戶端 send_message(pubsubPattern.client,message)
最后PUBLISH命令可以用一下偽代碼來描述:
def publish(channel,message): # 將消息發送給channel頻道的所有訂閱者 channel_publish(channel,message) #將消息發送給所有和channel 頻道相匹配的模式的訂閱者 pattern_publish(channel,message)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/23300.html
摘要:上一篇文章實戰第三章命令第五節有序集合下一篇文章實戰第三章命令第七節其他命令一般來說,發布與訂閱又稱的特點是訂閱者負責訂閱頻道,發送者負責向頻道發送二進制字符串消息。到目前為止,本書介紹的大多數命令都是與特定數據類型相關的。 上一篇文章:Python--Redis實戰:第三章:Redis命令:第五節:有序集合下一篇文章:Python--Redis實戰:第三章:Redis命令:第七節:其...
摘要:中的發布訂閱模型是一種消息通信模式,今天聊一下在中實現簡單的發布訂閱功能。參考自鏈接描述以上就是發布訂閱的簡單實現,如有錯誤,歡迎交流指正 redis中的發布/訂閱模型是一種消息通信模式,今天聊一下在python中實現簡單的發布訂閱功能。 實現方式一: redis_helper.py: 封裝發布訂閱方法 import redis ...
閱讀 2636·2021-11-11 16:55
閱讀 1279·2021-09-22 15:25
閱讀 1793·2019-08-29 16:26
閱讀 925·2019-08-29 13:21
閱讀 2306·2019-08-23 16:19
閱讀 2795·2019-08-23 15:10
閱讀 761·2019-08-23 14:24
閱讀 1850·2019-08-23 13:48