Python--Redis實戰:第三章:Redis命令:第六節:發佈與訂閱

上一篇文章: Python--Redis實戰:第三章:Redis命令:第五節:有序集合
下一篇文章: Python--Redis實戰:第三章:Redis命令:第七節:其餘命令

通常來講,發佈與訂閱(又稱pub/sub)的特色是訂閱者(listener)負責訂閱頻道(channel),發送者(publisher)負責向頻道發送二進制字符串消息(binary string message)。每當有消息被髮送至給定頻道時,頻道的全部訂閱者都會收到消息。咱們也能夠把頻道看做是電臺,其中訂閱者能夠同時收聽多個電臺,而發送者則能夠在任何電臺發送信息。redis

本節將對發佈與訂閱的相關操做進行介紹,閱讀這一節可讓讀者學會怎樣使用發佈與訂閱的相關命令,並瞭解到爲何本書在以後的章節裏面會使用其餘類似的解決方案來代替Redis提供的發佈與訂閱。segmentfault

下表展現了Redis提供的5個發佈與訂閱命令:服務器

命令 用例 用例描述
subscribe subscribe channel [channel ...] 訂閱給定的一個或多個頻道
unsubscribe unsubscribe [channnel channel ...] 退訂給定的一個或多個頻道,若是執行時沒有給定任何頻道,那麼退訂全部頻道
publish publish channel message 向給定頻道發送消息
psubscribe psubscribe pattern [pattern ...] 訂閱與給定模式相匹配的全部頻道
punsunscribe punsunscribe [pattern [pattern ...]] 退訂給定的模式,若是執行時沒有給定任何模式,那麼退訂全部模式。

考慮到publish命令和subscribe命令在Python客戶端的實現方式,一個比較簡單的演示發佈與訂閱的方法,就像下面代碼清單那樣使用輔助線程(helper thread)來執行publish命令:網絡

import redis  # 導入redis包包
import time,threading


# 與本地redis進行連接,地址爲:localhost,端口號爲6379

r = redis.StrictRedis(host='localhost', port=6379)

def publisher(n):
    #函數在開始執行時會先休眠,讓訂閱者有足夠的時間來鏈接服務器並監聽消息
    time.sleep(1)
    for i in range(n):
        r.publish('channel',i)
        #在發送消息以後進行短暫的休眠,讓消息能夠一條接一條地出現
        time.sleep(1)

def run_pubsub():
    #啓動發送者線程,並讓它發送三條消息
    threading.Thread(target=publisher,args=(3,)).start()
    #建立訂閱對象,並對它訂閱給定的頻道
    pubsub=r.pubsub()
    pubsub.subscribe(['channel'])
    count=0
    #經過遍歷函數pubsub.listen()的執行結果來監聽訂閱消息
    for item in pubsub.listen():
        #打印接收到的每條消息
        print(item)
        count+=1
        if count==4:
            pubsub.unsubscribe()
        if count==5:
            break

if __name__ == '__main__':
    run_pubsub()

運行結果:數據結構

{'type': 'subscribe', 'pattern': None, 'channel': b'channel', 'data': 1}
{'type': 'message', 'pattern': None, 'channel': b'channel', 'data': b'0'}
{'type': 'message', 'pattern': None, 'channel': b'channel', 'data': b'1'}
{'type': 'message', 'pattern': None, 'channel': b'channel', 'data': b'2'}
{'type': 'unsubscribe', 'pattern': None, 'channel': b'channel', 'data': 0}
在剛開始訂閱一個頻道的時候,客戶端會接收到一條關於被訂閱頻道的反饋。

在退訂頻道時,客戶端會接受到一條反饋信息,告知被退訂的是哪一個頻道,以及客戶端目前仍在訂閱的頻道數量。函數

雖然Redis的發佈與訂閱很是有用,但本書只在這一節和8.5節使用了這個模式,這樣作的緣由主要有如下兩個:操作系統

  • 第一個緣由和Redis系統的穩定性有關。對於舊版Redis來講,若是一個客戶端訂閱了某個或某些頻道,但它讀取消息的速度卻不夠快的話,那麼不斷積壓的消息會使得Redis輸出緩衝區的體積變得愈來愈大,這可能會致使Redis的速度變慢,甚至直接崩潰。也可能會致使Redis被操做系統強制殺死,甚至致使操做系統自己不可用。新版的Redis不會出現這種問題,由於它會自動斷開不符合client-output-buffer-limit pubsub配置選項要求的訂閱客戶端。
  • 第二個緣由和數據傳輸的可靠性有關。任何網絡系統在執行操做時均可能會遇到斷線狀況,而斷線產生的鏈接錯誤一般會使得網絡鏈接兩端的其中一端進行從新鏈接。本書使用的Python語言的Redis客戶端會在鏈接失效時自動進程從新鏈接,也會自動處理鏈接池(connection pool),諸如此類。可是,若是客戶端在執行訂閱操做的過程當中斷線,那麼客戶端將丟失在斷線期間發送的全部消息,所以依靠頻道來接受消息的用戶可能會對Redis提供的publish命令和subscribe命令的語義感到失望。

基於以上兩個緣由,本書在第六章編寫了兩個不一樣的方法來實現可靠的消息傳遞操做,這兩個方法除了能夠處理網絡斷線以外,還能夠防止Redis由於消息擠壓而耗費過多內存(這個方法即便對於舊版的Redis也是有效的)。線程

若是你喜歡簡單易用的publish命令和subscribe命令,而且可以承擔可能會丟失一小部分數據的風險,那麼你也能夠繼續使用Redis提供的發佈與訂閱特性,而不是8.5節中提供的實現,只要記得先把client-output-buffer-limit pubsub選項設置好就好了。code

到目前爲止,本書介紹的大多數命令都是與特定數據類型相關的。接下來的一節要介紹的命令你可能也會用到,但它們既不屬於Redis提供的5中數據結構,也不屬於發佈與訂閱特性。對象

上一篇文章: Python--Redis實戰:第三章:Redis命令:第五節:有序集合
下一篇文章: Python--Redis實戰:第三章:Redis命令:第七節:其餘命令
相關文章
相關標籤/搜索