Redis是內存中的數據結構存儲,用於緩存、高速數據攝取、處理消息隊列、分佈式鎖定等等。html
與其餘內存存儲相比,使用Redis的優點在於它提供了持久性和數據結構,好比列表、集合、排序集合和散列。python
在這篇文章中,介紹一個Redis keyspace通知的簡短概述。並演示如何配置Redis來接收它們。並展現如何在python中訂閱Redis通知git
在開始以前,請安裝並啓動Redis服務器,以下所述:https://redis.io/topics/quickstartgithub
默認狀況下,redis的通知事件是關閉的,在終端執行如下命令開啓:redis
$ redis-cli config set notify-keyspace-events KEA
OK
KEA字符串表示啓用了全部可能的事件。要查看每一個字符的含義,請查看文檔緩存
CLI 能夠在特殊模式下工做,容許您訂閱一個通道以接收消息。服務器
如今檢查事件是否起做用:數據結構
# 用於檢查事件 # psubscribe '*'表示咱們想訂閱全部帶有模式*的事件 $ redis-cli --csv psubscribe '*' Reading messages... (press Ctrl-C to quit) "psubscribe","*",1
開啓一個新的終端,設置一個值分佈式
127.0.0.1:6379> set key1 value1
OK
在上一個終端,會看到:ide
$ redis-cli --csv psubscribe '*' Reading messages... (press Ctrl-C to quit) "psubscribe","*",1 "pmessage","*","__keyspace@0__:key1","set" "pmessage","*","__keyevent@0__:set","key1
發現通知是工做中的
Redis的鍵盤空間通知從2.8.0版起就可使用了。對於更改任何Redis鍵的每一個操做,能夠配置Redis將消息發佈到發佈/訂閱。而後能夠訂閱這些通知。值得一提的是,事件僅在確實修改了鍵的狀況下才生成。例如,刪除不存在的鍵將不會生成事件。
以上收到三個事件:
"psubscribe","*",1 "pmessage","*","__keyspace@0__:key1","set" "pmessage","*","__keyevent@0__:set","key1
事件是經過Redis的Pub/Sub層交付的。
爲了訂閱channel channel1和channel2,客戶端發出帶有通道名稱的subscribe命令
第一步,須要python操做redis的包
$ pip install redis
事件循環,請看如下代碼:
import time from redis import StrictRedis redis = StrictRedis(host='localhost', port=6379) # redis 發佈訂閱 pubsub = redis.pubsub() # 監聽通知 pubsub.psubscribe('__keyspace@0__:*') # 開始消息循環 print('Starting message loop') while True: # 獲取消息 message = pubsub.get_message() if message: print(message) else: time.sleep(0.01)
分析:
這是建立 `redis` 鏈接的代碼
redis = StrictRedis(host='localhost', port=6379)
默認狀況下,全部響應都以字節的形式返回。用戶負責解碼。若是客戶機的全部字符串響應都應該被解碼,那麼用戶能夠指定decode_responses=True to StrictRedis。在這種狀況下,任何返回字符串類型的Redis命令都將用指定的編碼進行解碼。
接下來,建立一個訂閱頻道並偵聽新消息的pubsub對象:
pubsub = redis.pubsub() pubsub.psubscribe('__keyspace@0__:*')
繼而經過一個無限循環來等待事件
while True: message = pubsub.get_message() ...
若是有數據,get_message()將讀取並返回它。若是沒有數據,該方法將不返回任何數據。
從pubsub實例中讀取的每條消息都是一個字典,其中包含如下鍵:
如今啓動 `python` 腳本,在終端中設置一個key值
127.0.0.1:6379> set mykey myvalue
OK
將看到腳本如下輸出
$ python subscribe.py Starting message loop {'type': 'psubscribe', 'data': 1, 'channel': b'__keyspace@0__:*', 'pattern': None} {'type': 'pmessage', 'data': b'set', 'channel': b'__keyspace@0__:mykey', 'pattern': b'__keyspace@0__:*'}
註冊回調函數來處理已發佈的消息。消息處理程序接受一個參數,即消息。要使用消息處理程序訂閱通道或模式,請將通道或模式名稱做爲關鍵字參數傳遞,其值爲回調函數。當使用消息處理程序在通道或模式上讀取消息時,將建立消息字典並將其傳遞給消息處理程序。在這種狀況下,get_message()返回一個None值,由於消息已經被處理
import time from redis import StrictRedis redis = StrictRedis(host='localhost', port=6379) pubsub = redis.pubsub() def event_handler(msg): print('Handler', msg) pubsub.psubscribe(**{'__keyspace@0__:*': event_handler}) print('Starting message loop') while True: message = pubsub.get_message() if message: print(message) else: time.sleep(0.01)
選擇是在單獨的線程中運行事件循環
import time from redis import StrictRedis redis = StrictRedis(host='localhost', port=6379) def event_handler(msg): print(msg) thread.stop() pubsub = redis.pubsub() pubsub.psubscribe(**{'__keyevent@0__:expired': event_handler}) thread = pubsub.run_in_thread(sleep_time=0.01)
Redis的一個常見用例是,應用程序須要可以響應存儲在特定鍵或鍵中的值可能發生的更改。因爲有了鍵盤空間通知和發佈/訂閱,能夠對Redis數據中的變化作出響應。通知很容易使用,而事件處理器可能在地理位置上分佈。
最大的缺點是,Pub/Sub的實現要求發佈者和訂閱方始終處於啓動狀態。用戶在中止或鏈接丟失時丟失數據。