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