Redis訂閱與釋出
釋出與訂閱模型在許多程式語言中都有實現,也就是我們經常說的設計模式中的一種--觀察者模式。在一些應用場合,例如傳送方並不是以固定頻率傳送訊息,如果接收方頻繁去諮詢傳送方,這種操作無疑是很麻煩並且不友好的。
舉個生活的例子,一個喜歡購買鮮牛奶的人,需要每天在上班的時候/下班的時候都專門去牛奶店購買鮮牛奶,但不一定每天去到那裡都剛好有自己喜歡的那一種牛奶,這個時候,這個人跑老遠的距離都白費了。但如果這個人去牛奶店一次性訂閱了一個月的某種牛奶,那麼他就不用擔憂今天是否能買到鮮牛奶了,只要送奶員把牛奶送到他家樓下的箱子裡面就行。
而訂閱釋出模型與這個例子有點類似,訂閱者只要訂閱註冊某個頻道就可以“高枕無憂”了,當有訊息傳送過來的時候,會通過訂閱的頻道接收。優勢在於把耦合點獨立分離處理,作為釋出方和接收方的中介,實現了釋出方和接收方的隔離,
訂閱與釋出系統是Redis的一個高階屬性,多個客戶端可以同時訂閱同一個頻道,類似廣播的機制。所不同的是,一個客戶端可以同時訂閱多個頻道。
樣例圖:
Redis 訂閱釋出系統,伺服器在背後的工作:
伺服器中維護著一個pubsub_channels字典,所有的頻道和訂閱關係都儲存在這裡。字典的鍵為頻道的名稱,而值為訂閱頻道的客戶端連結串列。
1. 當有新的客戶端訂閱某個頻道時,會發生兩種情況中的一種:
1)如果頻道已經存在,則新的客戶端會新增到pubsub_channels對應頻道的連結串列末尾
2)如果頻道原本不存在,則會為頻道建立一個鍵,該客戶端成為連結串列的第一個元素
2. 當一個客戶端退訂一個頻道的時候:
pubsub_channels對應鍵的連結串列會刪除該客戶端
3. 傳送資訊
伺服器會遍歷pubsub_channels中對應鍵的連結串列,向每一個客戶端傳送資訊
伺服器還維護著一個pubsub_patterns連結串列,連結串列的pattern屬性記錄了被訂閱的模式,而client屬性記錄了訂閱模式的客戶端
1. 當有新的客戶端訂閱某個模式的時,會進行如下步驟:
1)建立一個連結串列節點,pattern屬性記錄訂閱的模式,client記錄訂閱模式的客戶端
2)將這個連結串列節點新增到pubsub_patterns連結串列中
2. 當一個客戶端退訂某一個模式的時候:
伺服器遍歷pubsob_patterns找到對應的pattern同時也是對應該client客戶端的節點,將改節點刪除
3. 傳送資訊
伺服器遍歷pubsub_channels,查詢與channels頻道相匹配的模式麻將訊息傳送給訂閱了這些模式的客戶端。
Redis 訂閱系統的優勢:
1. 當一個客戶端向頻道傳送一個資訊,訂閱了同一個頻道/模式的多個客戶端可以同時接收到資訊,類似廣播的機制。
2. 便於Sentinel哨兵與伺服器間的通訊並進行監控
1. 訂閱頻道
命令格式:
SUSCRIBE channel1 [channel2] [channel3]
例如(同時訂閱兩個頻道):
redis> subscribe local_system remote_system
Reading messages... (press Ctrl-C to quit)
1) "subscribe" # 返回值的型別:顯示訂閱成功
2) "local_system" # 訂閱的頻道名字
3)"remote _system "
4) (integer) 2 # 目前已訂閱的頻道數量
訂閱和接收者:
傳送者:
注意:客戶端一點與某個頻道建立連線就不能進行其他操作,一旦客戶端退出連線,訂閱的頻道自動會斷開。
2. 訂閱模式
PSUBSCRIBE pattern1 [pattern2] [pattern3]
pattern可以用 符號 * 進行模糊匹配,例如:
remo* #匹配以remo開頭的模式
*system #匹配以system結尾的模式
例如:
客戶端1
客戶端2
注意:返回的integer為1是指匹配了一個模式,實際上是匹配了兩個頻道。
釋出資訊命令:
客戶端:
3. 取消訂閱:
命令:
1)取消訂閱頻道
UNSUBSCRIBE channel1 [channel2]
2)取消訂閱模式
PUNSUBSCRIBE [pattern [pattern …]]
由於在客戶端介面無法實現,這裡就不展示了。而在程式設計過程中是可以實現的。
關於python中的程式設計,可以看看這篇文章:
http://www.cnblogs.com/anpengapple/p/7027979.html
4. 釋出訊息
命令:
PUBLISH channel message
向一個頻道傳送資訊,所有訂閱這個頻道的客戶端都會接收到資訊
5. 檢視已有的頻道
命令:
PUBSUB subcommand [argument [argument ...]]
subcommand子命令:
1)PUBSUB CHANNELS [pattern]
列出當前的活躍頻道
如果給定pattern引數,則會返回伺服器當前被訂閱的頻道中與pattern模式相匹配的頻道
2)PUBSUB NUMSUB [channel-1 … channel-N]
返回給定頻道的訂閱者數量, 訂閱模式的客戶端不計算在內
因為有一個是匹配模式,所以返回的interger值為1
3)PUBSUB NUMPAT
返回訂閱模式的數量
Sentinel 哨兵中的應用:
Sentinel伺服器與Master伺服器/Slave伺服器之間的訂閱釋出系統是Sentinl監控過程的一個重要環節,通過訂閱釋出系統達到監控伺服器狀態的作用。其執行原理與上面的客戶端伺服器之間的訂閱機制無太大區別,都是基於網路連線的資料傳輸。Sentinel之間的通訊也是通過Sentinel與服務武器間的這個訂閱釋出系統實現的,一個Sentinel通過伺服器的頻道傳送資訊,其他Sentinel就會接收到。
參考文章:
http://www.cnblogs.com/anpengapple/p/7027979.html
《redis設計與實現》