1. 程式人生 > >Redis入門【八】---------釋出與訂閱(pub/sub)

Redis入門【八】---------釋出與訂閱(pub/sub)

前言

一般來說,釋出(publish)與訂閱(subscribe),又稱為pub/sub的。其特點是訂閱者(listener)負責訂閱頻道(channel),傳送者(publisher)負責向頻道傳送二進位制字串訊息。

每當有訊息傳送到頻道的時候,頻道的所有訂閱者都會收到訊息,其實我們可以把頻道理解為電臺,訂閱者可以同時收聽多個電臺,而傳送者可以再任何電臺傳送訊息

頻道的訂閱與資訊傳送

下面就是訂閱的一個關係,三個客戶端同時去訂閱subscribe一個頻道channel

這時候通過命令publish向頻道chnnel傳送資訊的時候,其他三個客戶端就會收到同樣的資訊。

常用命令

#<1>訂閱一個或者多個指定的頻道
subscribe channel [channel ...]
#<2>退訂給定的一個或多個頻道,如果沒有指定則表示退訂所有的
unsubscribe [channel [channel ...]]
#<3>給定頻道傳送訊息
publish channel message
#<4>訂閱給定模式相匹配的所有頻道
psubscribe pattern [pattern ...]
#<5>退訂給定的模式,如果沒有給定則表示退訂所有模式
punsubscribe [pattern [pattern ...]]

具體操作

內部實現

訂閱

每個 Redis 伺服器程序都維持著一個表示伺服器狀態的 redis.h/redisServer 結構, 結構的 pubsub_channels 屬性是一個字典, 這個字典就用於儲存訂閱頻道的資訊

struct redisServer {
    dict *pubsub_channels;
    // ...
};

某個客戶端訂閱頻道的時候,redis需要將該頻道和該客戶端繫結。首先,在客戶端結構體client中,有一個屬性為pubsub_channels,該屬性表明了該客戶端訂閱的所有頻道,它是一個字典型別,通過雜湊表實現,其中的每個元素都包含了一個鍵值對以及指向下一個元素的指標,每次訂閱都要向其中插入一個結點,鍵表示訂閱的頻道

值為空

然後,在表示伺服器端的結構體redisServer中,也有一個屬性為pubsub_channels,但此處它表示的是該伺服器端中的所有頻道以及訂閱了這個頻道的客戶端,它也是一個字典型別,插入結點時,鍵表示頻道值則是訂閱了這個頻道的所有客戶端組成的連結串列。最後Redis通知客戶端其訂閱成功。 

例如client2,client5,client1都訂閱了channel頻道,而其他頻道也分別被別的客戶端所訂閱,就是下面的場景

服務端中所有頻道與客戶端的關係

通過 pubsub_channels 字典, 程式只要檢查某個頻道是否為字典的鍵, 就可以知道該頻道是否正在被客戶端訂閱; 只要取出某個鍵的值, 就可以得到所有訂閱該頻道的客戶端的資訊。

傳送

當呼叫 publish channel message 命令, 程式首先根據 channel 定位到字典的鍵, 然後將資訊傳送給字典值連結串列中的所有客戶端。比如說,對於上面的例子,如果某個客戶端執行命令 publish channel1 "hello redis" ,那麼 client2 、 client5 和 client1 三個客戶端都將接收到 "hello redis" 資訊

退訂

使用unscribe命令可以退訂指定的頻道, 這個命令執行的是訂閱的反操作: 它從 pubsub_channels 字典的給定頻道(鍵)中, 刪除關於當前客戶端的資訊, 這樣被退訂頻道的資訊就不會再發送給這個客戶端。