當一個客戶端執行SUBSCRIBE命令訂閱某個或某些頻道時,這個客戶端與被訂閱頻道之間就創建起了一種訂閱關係。redis
Redis將全部頻道的訂閱關係保存在服務器狀態的pubsub_channels字典裏面,這個字典的鍵是某個被訂閱的頻道,而鍵的值是一個鏈表,鏈表裏面記錄了全部訂閱這個頻道的客戶端:服務器
struct redisServer{ //保存全部頻道的訂閱關係 dict *pubsub_channels; }
若是頻道已經有其餘的訂閱者,那麼他在pubsub_channels字典中必然有相應的訂閱者鏈表,程序惟一要作的就是將客戶端添加到訂閱者鏈表的末尾,反之程序首先要在pubsub_channels字典中爲頻道建立一個鍵,並將這個鍵的值設置爲空鏈表,而後將客戶端添加到鏈表,成爲鏈表的第一個元素。學習
UNSUBSCRIBE命令的行爲與SUBSCRIBE命令相反,當一個客戶端推定某個或某些頻道的時候,服務器將從pubsub_channels中接觸客戶端與被訂閱頻道之間的關聯:程序會根據被推定頻道的名字,在publish_channels字典中找到頻道對應的訂閱鏈表,然後從訂閱者鏈表中刪除退訂客戶端的信息;若是刪除推定客戶端以後,頻道的訂閱者鏈表變成空鏈表,那麼說明頻道已經沒有了訂閱者了,程序將從pubsub_channels字典中刪除頻道對應的鍵。spa
服務器將全部頻道的訂閱關係都保存在服務器狀態的pubsub_channels屬性裏面,與之類似,服務器也將全部模式的訂閱關係都保存在服務器狀態的pubsub_patterns屬性裏面:設計
struct redisServer { //保存全部訂閱關係 list *pubsub_patterns; };
pubsub_patterns屬性是一個鏈表,鏈表中的每一個節點都包含着一個pubsubpattern結構,這個結構的pattern屬性記錄了被訂閱的模式,而client屬性則記錄了訂閱模式的客戶端:code
typedef struct pubsubPattern{ //訂閱模式的客戶端 redisClient *client; //被訂閱的模式 robj *pattern; } pubsubPattern;
訂閱模式blog
每當客戶端執行PSUBSCRIBE命令訂閱某個或某些模式的時候,服務器會對某個被訂閱的模式執行:新建一個pubsubPattern結構,將結構的pattern屬性設置爲被訂閱的模式,client屬性設置爲訂閱模式的客戶端;將pubsubPattern結構添加到pubsub_patterns鏈表的表尾。class
發送消息cli
當一個Redis客戶端執行PUBLISH < channel > < message > 命令將消息message發送給頻道channel的時候,服務器須要執行如下兩個動做:將消息message發送給channel頻道的全部訂閱者;若是有一個或多個模式pattern與頻道channel相匹配,那麼將消息message發送給pattern模式的訂閱者。遍歷
由於服務器狀態中pubsub_channels字典記錄了全部頻道的訂閱關係,因此爲了將消息發送給channel頻道的全部訂閱者,PUBLISH命令要作的就是在subsub_channels字典裏找到頻道channel的訂閱者名單(鏈表),而後將消息發送給名單上的全部客戶端。
將消息發送欸模式訂閱者,由於服務器狀態中的pubsub_patterns鏈表記錄了全部模式的訂閱關係,因此爲了將消息發送給全部與channel頻道相匹配的模式的訂閱者,PUBLISH命令要作的就是遍歷整個pubsub_patterns鏈表,查找那些與channel頻道相匹配的模式,並將消息發送給訂閱了謝謝模式的客戶端。
PUBSUB CHANNELS 【pattern】子命令用於返回服務器當前被訂閱的頻道,若是【pattern】參數不給定,那麼命令返回服務器當前被訂閱的全部頻道。
PUBSUB NUMSUB 子命令接收任意多個頻道做爲輸入參數,並返回這些頻道的訂閱者數量。
PUBSUB NUMPAT子命令用於返回服務器當前訂閱模式的數量
天天學一點,總會有收穫。
說明:尊重做者知識產權,文中內容參考《Redis設計與實現》,僅在此作學習與你們分享。