Redis的發(fā)布與訂閱功能由PUBLISH瞬哼、SUBSCRIBE被碗、PSUBSCRIBE等命令組成藻肄。通過(guò)SUBSCRIBE命令木柬,客戶端可以訂閱一個(gè)或者多個(gè)頻道缰雇,每當(dāng)有其他客戶端向被訂閱的頻道發(fā)送消息時(shí)入偷,頻道的所有訂閱者都會(huì)收到消息。另外械哟,客戶端還可以通過(guò)PSUBSCRIBE訂閱一個(gè)或多個(gè)模式盯串。
頻道的訂閱與退訂
Redis將所有頻道的訂閱關(guān)系都保存在服務(wù)器狀態(tài)的pubsub_channels字典里,鍵為頻道戒良,值為一個(gè)鏈表体捏,鏈表節(jié)點(diǎn)是訂閱了該頻道的客戶端:
struct redisServer {
... ...
dict *pubsub_channels; // 保存所有頻道的訂閱關(guān)系
list *pubsub_patterns; // 保存所有模式訂閱關(guān)系
... ....
};
每當(dāng)客戶端執(zhí)行SUBSCRIBE命令時(shí),服務(wù)器都會(huì)將客戶端與被訂閱的頻道在pubsub_channels里關(guān)聯(lián):
- 若頻道已有其他訂閱者糯崎,則pubsub_channels字典中必有相應(yīng)的訂閱著鏈表几缭,只需將客戶端添加到鏈表的末尾;
- 若頻道還未有訂閱者沃呢,則需先在pubsub_channels中為該頻道創(chuàng)建一個(gè)鍵年栓,值設(shè)置為空,再將客戶端添加進(jìn)鏈表薄霜。
客戶端可通過(guò)UNSUBSCRIBE命令退訂頻道某抓,服務(wù)器將從pubsub_channels中解除客戶端與被退訂頻道之間的關(guān)聯(lián):
- 在pubsub_channels中找到頻道對(duì)應(yīng)的訂閱者鏈表纸兔,然后刪除鏈表中退訂客戶端信息;
-
若刪除退訂客戶端之后否副,對(duì)應(yīng)鏈表變成空鏈表汉矿,則從pubsub_channels中刪除對(duì)應(yīng)的鍵。
模式的訂閱與退訂
服務(wù)器將所有模式的訂閱關(guān)系都保存在服務(wù)器狀態(tài)的pubsub_patterns屬性中备禀,pubsub_patterns是一個(gè)鏈表洲拇,鏈表節(jié)點(diǎn)是一個(gè)pubsubPattern結(jié)構(gòu):
typedef struct pubsubPattern {
redisClient *client; // 訂閱模式的客戶端
robj *pattern; // 被訂閱的模式
} pubsubPattern;
每當(dāng)客戶端執(zhí)行PSUBSCRIBE命令訂閱某個(gè)或某些模式時(shí),服務(wù)器會(huì)對(duì)每個(gè)訂閱模式執(zhí)行以下操作:
- 新建一個(gè)pubsubPattern結(jié)構(gòu)曲尸,將結(jié)構(gòu)中的pattern設(shè)置為被訂閱的模式赋续,client設(shè)置為訂閱模式的客戶端;
- 將pubsubPattern結(jié)構(gòu)添加到pubsub_patterns的末尾另患。
當(dāng)客戶端執(zhí)行PUNSUBSCRIBE命令退訂模式時(shí)纽乱,服務(wù)器將在pubsub_patterns鏈表中查找并刪除pattern為被退訂模式,client為執(zhí)行退訂命令的客戶端的pubsubPattern結(jié)構(gòu)昆箕。
發(fā)送消息
當(dāng)一個(gè)Redis客戶端執(zhí)行以下命令發(fā)送消息時(shí)迫淹,服務(wù)器需執(zhí)行以下操作:
PUBLISH <channel> <message>
- 將消息message發(fā)送給channel頻道的所有訂閱者;
- 如果有模式與頻道channel相匹配为严,那么將message發(fā)送給pattern模式的訂閱者敛熬。