W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
當一個客戶端執(zhí)行 SUBSCRIBE 命令, 訂閱某個或某些頻道的時候, 這個客戶端與被訂閱頻道之間就建立起了一種訂閱關系。
Redis 將所有頻道的訂閱關系都保存在服務器狀態(tài)的 pubsub_channels
字典里面, 這個字典的鍵是某個被訂閱的頻道, 而鍵的值則是一個鏈表, 鏈表里面記錄了所有訂閱這個頻道的客戶端:
struct redisServer {
// ...
// 保存所有頻道的訂閱關系
dict *pubsub_channels;
// ...
};
比如說, 圖 IMAGE_PUBSUB_CHANNELS 就展示了一個 pubsub_channels
字典示例, 這個字典記錄了以下信息:
client-1
、 client-2
、 client-3
三個客戶端正在訂閱 "news.it"
頻道。client-4
正在訂閱 "news.sport"
頻道。client-5
和 client-6
兩個客戶端正在訂閱 "news.business"
頻道。每當客戶端執(zhí)行 SUBSCRIBE 命令, 訂閱某個或某些頻道的時候, 服務器都會將客戶端與被訂閱的頻道在 pubsub_channels
字典中進行關聯(lián)。
根據(jù)頻道是否已經(jīng)有其他訂閱者, 關聯(lián)操作分為兩種情況執(zhí)行:
pubsub_channels
字典中必然有相應的訂閱者鏈表, 程序唯一要做的就是將客戶端添加到訂閱者鏈表的末尾。pubsub_channels
字典, 程序首先要在 pubsub_channels
字典中為頻道創(chuàng)建一個鍵, 并將這個鍵的值設置為空鏈表, 然后再將客戶端添加到鏈表, 成為鏈表的第一個元素。舉個例子, 假設服務器 pubsub_channels
字典的當前狀態(tài)如圖 IMAGE_PUBSUB_CHANNELS 所示, 那么當客戶端 client-10086
執(zhí)行命令:
SUBSCRIBE "news.sport" "news.movie"
之后, pubsub_channels
字典將更新至圖 IMAGE_AFTER_SUBSCRIBE 所示的狀態(tài), 其中用虛線包圍的是新添加的節(jié)點:
pubsub_channels
字典新增了 "news.movie"
鍵, 該鍵對應的鏈表值只包含一個 client-10086
節(jié)點, 表示目前只有 client-10086
一個客戶端在訂閱 "news.movie"
頻道。"news.sport"
頻道, client-10086
的節(jié)點放在了頻道對應鏈表的末尾, 排在 client-4
節(jié)點的后面。SUBSCRIBE 命令的實現(xiàn)可以用以下偽代碼來描述:
def subscribe(*all_input_channels):
# 遍歷輸入的所有頻道
for channel in all_input_channels:
# 如果 channel 不存在于 pubsub_channels 字典(沒有任何訂閱者)
# 那么在字典中添加 channel 鍵,并設置它的值為空鏈表
if channel not in server.pubsub_channels:
server.pubsub_channels[channel] = []
# 將訂閱者添加到頻道所對應的鏈表的末尾
server.pubsub_channels[channel].append(client)
UNSUBSCRIBE 命令的行為和 SUBSCRIBE 命令的行為正好相反 —— 當一個客戶端退訂某個或某些頻道的時候, 服務器將從 pubsub_channels
中解除客戶端與被退訂頻道之間的關聯(lián):
pubsub_channels
字典中找到頻道對應的訂閱者鏈表, 然后從訂閱者鏈表中刪除退訂客戶端的信息。pubsub_channels
字典中刪除頻道對應的鍵。舉個例子, 假設 pubsub_channels
的當前狀態(tài)如圖 IMAGE_BEFORE_UNSUBSCRIBE 所示, 那么當客戶端 client-10086
執(zhí)行命令:
UNSUBSCRIBE "news.sport" "news.movie"
之后, 圖中用虛線包圍的兩個節(jié)點將被刪除, 如圖 IMAGE_AFTER_UNSUBSCRIBE 所示:
pubsub_channels
字典更新之后, client-10086
的信息已經(jīng)從 "news.sport"
頻道和 "news.movie"
頻道的訂閱者鏈表中被刪除了。client-10086
之后, 頻道 "news.movie"
已經(jīng)沒有任何訂閱者, 因此鍵 "news.movie"
也從字典中被刪除了。UNSUBSCRIBE 命令的實現(xiàn)可以用以下偽代碼來描述:
def unsubscribe(*all_input_channels):
# 遍歷要退訂的所有頻道
for channel in all_input_channels:
# 在訂閱者鏈表中刪除退訂的客戶端
server.pubsub_channels[channel].remove(client)
# 如果頻道已經(jīng)沒有任何訂閱者了(訂閱者鏈表為空)
# 那么將頻道從字典中刪除
if len(server.pubsub_channels[channel]) == 0:
server.pubsub_channels.remove(channel)
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: