Redis 有個 Pub/Sub 的功能,簡單來說,就是可以發佈(publish)消息或者訂閱(subscribe)消息的功能。訂閱方跟發佈消息(message)方,都是透過所謂的 Channel 傳遞與接受訊息。

相較於選擇 RabbitMQ 這種重量級的 message broker, 如果是一些簡單的應用(Application) 其實也可以考慮選擇利用 Redis 的 Pub/Sub 達到訊息傳遞的目的。

本文簡單紀錄如何在 Python 中使用 Redis 的 Pub/Sub 。

本文環境

  • Python 3.6.5
  • redis 2.10.6
$ pip install redis

發佈

發佈的功能十分簡單,只要用 publish() 方法即可,以下範例就是利用 publish()GREETING 字串送到 my_redis_channel 這個 Channel 。

import redis


r = redis.Redis(host='localhost', port=6379, db=0)
r.publish(
    'my_redis_channel',
    'GREETING',
)

訂閱

訂閱則使用 pubsub() 方法取得一個 PubSub object, 接著就能夠使用 subscribe() 方法訂閱 1 至多個 channel ,再來使用 listen() 方法監聽 Channel 內發佈的訊息。

p.s. 訂閱多個 Channel 範例 sub.subscribe('channel_1', 'channel_2')

p.s. 除了 subscribe() 方法之外,還有一個 psubscribe 方法能夠以字串匹配的方式一次訂閱多個 Channel, 例如: psubscribe('my_redis_*') 代表 my_redis_ 開頭的 Channel 都會訂閱。

listen() 方式取得的訊息是一個 dictionary ,含有以下 key 值:

  • type 訊息的類型,共有 subscribe, unsubscribe, psubscribe, punsubscribe, message, pmessage 6 種
  • channel Channel 名稱
  • pattern 如果是利用 psubscribe 訂閱的 Channel ,這邊就會顯示匹配的模式,例如 my_redis_*
  • data 訊息內的資料

訂閱範例如下:

import redis


r = redis.Redis(host='localhost', port=6379, db=0)
sub = r.pubsub()
sub.subscribe('my_redis_channel')
for message in sub.listen():
    print('Got message', message)
    if (
        isinstance(message.get('data'), bytes) and
        message['data'].decode() == 'GREETING'
    ):
        print('Hello')

p.s. 由於字串被發佈到 redis 後會被轉為 bytes, 因此上述範例判斷 data 是 bytes 的情況下,才會用 decode() 方法轉為 Python 的 str

以上, Happy Coding!

References

https://pypi.org/project/redis/