Redis提供了基於「發佈/訂閱」模式的消息機制,此種模式下,消息發佈者和訂閱者不進行直接通訊,發佈者客戶端向指定的頻道(channel)發佈消息,訂閱該頻道的每一個客戶端均可以收到該消息(頻道沒有」建立「的概念,能夠直接訂閱、亦可直接發佈消息)。python
自2.0.0可用。redis
時間複雜度:O(N+M),其中
N
是頻道channel
的訂閱者數量,而M
則是使用模式訂閱(subscribed patterns)的客戶端的數量。shell
將信息 message
發送到指定的頻道 channel
。segmentfault
接收到信息 message
的訂閱者數量。測試
# 向沒有訂閱者的頻道發送信息 coderknock> PUBLISH new_channel "test publish" (integer) 0 # 向有訂閱者的頻道發送信息 coderknock> PUBLISH channel1 "new channel1" (integer) 1
自2.0.0可用。ui
時間複雜度:O(N),其中
N
是訂閱的頻道的數量。命令行
訂閱給定的一個或多個頻道的信息。code
接收到的信息(請參見下面的代碼說明)。blog
coderknock> SUBSCRIBE channel1 Reading messages... (press Ctrl-C to quit) # 訂閱成功 1) "subscribe" # 返回值的類型:顯示訂閱成功 2) "channel1" # 訂閱的頻道名字 3) (integer) 1 # 目前已訂閱的頻道數量 # 接收到信息 1) "message" # 返回值的類型:信息 2) "channel1" # 來源(從哪一個頻道發送過來) 3) "new channel1" # 信息內容
#### PSUBSCRIBE隊列
自2.0.0可用。
時間複雜度:O(N),
N
是訂閱的模式的數量。
訂閱一個或多個符合給定模式的頻道。
每一個模式以 *
做爲匹配符,好比 it*
匹配全部以 it
開頭的頻道( it.news
、 it.blog
、 it.tweets
等等), news.*
匹配全部以 news.
開頭的頻道( news.it
、 news.global.today
等等),諸如此類。
接收到的信息(請參見下面的代碼說明)。
coderknock> PSUBSCRIBE news.* coderknock.* Reading messages... (press Ctrl-C to quit) # 訂閱成功 1) "psubscribe" # 返回值的類型:顯示訂閱成功 2) "news.*" # 訂閱的頻道名字 3) (integer) 1 # 目前已訂閱的頻道數量 1) "psubscribe" 2) "coderknock.*" 3) (integer) 2 # 接收到信息 1) "pmessage" # 返回值的類型:信息 2) "news.*" # 來源頻道模式 3) "news.123" # 具體頻道(從哪一個頻道發送過來) 4) "123 # 消息 1) "pmessage" 2) "news.*" 3) "news.222" 4) "222"
### 查看發佈/訂閱系統狀態
### PUBSUB
自2.8.0可用。
時間複雜度:O(N),
N
是訂閱的模式的數量。
PUBSUB
是一個查看訂閱與發佈系統狀態的內省命令, 它由數個不一樣格式的子命令組成, 如下將分別對這些子命令進行介紹。
列出當前的活躍頻道。
活躍頻道指的是那些至少有一個訂閱者的頻道, 訂閱模式的客戶端不計算在內。
pattern
參數是可選的:
若是不給出 pattern
參數,那麼列出訂閱與發佈系統中的全部活躍頻道。
若是給出 pattern
參數,那麼只列出和給定模式 pattern
相匹配的那些活躍頻道。
N
爲活躍頻道的數量(對於長度較短的頻道和模式來講,將進行模式匹配的複雜度視爲常數)。# 客戶端1 coderknock> SUBSCRIBE coderknock sanchan news test Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "coderknock" 3) (integer) 1 1) "subscribe" 2) "sanchan" 3) (integer) 2 1) "subscribe" 2) "news" 3) (integer) 3 1) "subscribe" 2) "test" 3) (integer) 4 # 客戶端2 coderknock> SUBSCRIBE coderknock sanchan blog oschina Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "coderknock" 3) (integer) 1 1) "subscribe" 2) "sanchan" 3) (integer) 2 1) "subscribe" 2) "blog" 3) (integer) 3 1) "subscribe" 2) "oschina" 3) (integer) 4 # 統計出的有訂閱的頻道 coderknock> PUBSUB CHANNELS 1) "coderknock" 2) "sanchan" 3) "blog" 4) "news" 5) "oschina" 6) "test" # 統計頻道名包含 o 的頻道 coderknock> PUBSUB CHANNELS *o* 1) "coderknock" 2) "blog" 3) "oschina" #咱們關閉客戶端1,只有客戶端1訂閱的 "news" "test" 頻道消失 coderknock> PUBSUB CHANNELS 1) "blog" 2) "oschina" 3) "coderknock" 4) "sanchan" # 從新訂閱 # 客戶端1 coderknock>PSUBSCRIBE news.* coderknock.* Reading messages... (press Ctrl-C to quit) 1) "psubscribe" 2) "news.*" 3) (integer) 1 1) "psubscribe" 2) "coderknock.*" 3) (integer) 2 # 客戶端2 coderknock> PSUBSCRIBE sanchan.* coderknock.* Reading messages... (press Ctrl-C to quit) 1) "psubscribe" 2) "sanchan.*" 3) (integer) 1 1) "psubscribe" 2) "coderknock.*" 3) (integer) 2 # 客戶端3 coderknock> PSUBSCRIBE sanchan.* coderknock.* news blog Reading messages... (press Ctrl-C to quit) 1) "psubscribe" 2) "sanchan.*" 3) (integer) 1 1) "psubscribe" 2) "coderknock.*" 3) (integer) 2 1) "psubscribe" 2) "news" 3) (integer) 3 1) "psubscribe" 2) "blog" 3) (integer) 4 # 說明不會統計 PSUBSCRIBE 訂閱 coderknock> PUBSUB CHANNELS (empty list or set)
返回給定頻道的訂閱者數量, 訂閱模式的客戶端不計算在內。
N
爲給定頻道的數量。channel-1
, channel-1
的訂閱者數量,頻道 channel-2
, channel-2
的訂閱者數量,諸如此類。 回覆中頻道的排列順序和執行命令時給定頻道的排列順序一致。 不給定任何頻道而直接調用這個命令也是能夠的, 在這種狀況下, 命令只返回一個空列表。# 訂閱的客戶端 #客戶端1 coderknock> SUBSCRIBE coderknock sanchan blog oschina Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "coderknock" 3) (integer) 1 1) "subscribe" 2) "sanchan" 3) (integer) 2 1) "subscribe" 2) "blog" 3) (integer) 3 1) "subscribe" 2) "oschina" 3) (integer) 4 #客戶端2 coderknock> SUBSCRIBE coderknock sanchan news test Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "coderknock" 3) (integer) 1 1) "subscribe" 2) "sanchan" 3) (integer) 2 1) "subscribe" 2) "news" 3) (integer) 3 1) "subscribe" 2) "test" 3) (integer) 4 #客戶端3 coderknock> PSUBSCRIBE sanchan.* coderknock.* news blog Reading messages... (press Ctrl-C to quit) 1) "psubscribe" 2) "sanchan.*" 3) (integer) 1 1) "psubscribe" 2) "coderknock.*" 3) (integer) 2 1) "psubscribe" 2) "news" 3) (integer) 3 1) "psubscribe" 2) "blog" 3) (integer) 4 # 統計,能夠看到 PSUBSCRIBE 訂閱一樣不會被統計並且不支持模式匹配 coderknock> PUBSUB NUMSUB coderknock news blog oschina test sanchan coderknock.* 1) "coderknock" 2) (integer) 2 3) "news" 4) (integer) 1 5) "blog" 6) (integer) 1 7) "oschina" 8) (integer) 1 9) "test" 10) (integer) 1 11) "sanchan" 12) (integer) 2 13) "coderknock.*" 14) (integer) 0
返回 訂閱模式 的數量。
注意, 這個命令返回的不是訂閱模式的客戶端的數量, 而是客戶端訂閱的全部模式的數量總和。
N
爲給定頻道的數量。#採用上面示例中的訂閱客戶端,這裏統計的 訂閱模式 包含 PSUBSCRIBE 訂閱 coderknock> PUBSUB NUMPAT (integer) 8 # 添加一個客戶端4 coderknock> PSUBSCRIBE blog* Reading messages... (press Ctrl-C to quit) 1) "psubscribe" 2) "blog*" 3) (integer) 1 # 統計會發現模式增長 1 coderknock> PUBSUB NUMPAT (integer) 9
### 退訂
#### UNSUBSCRIBE
自2.0.0可用。
時間複雜度:O(N) ,
N
是客戶端已訂閱的頻道的數量。
指示客戶端退訂給定的頻道。
若是沒有頻道被指定,也便是,一個無參數的 UNSUBSCRIBE
調用被執行,那麼客戶端使用 SUBSCRIBE
命令訂閱的全部頻道都會被退訂。在這種狀況下,命令會返回一個信息,告知客戶端全部被退訂的頻道。
這個命令在不一樣的客戶端中有不一樣的表現。
在命令行中該命令沒法測試(訂閱後命令行會阻塞),咱們使用 python 進行測試:
import redis import time r = redis.StrictRedis(host='127.0.0.1', password='admin123', port=6379, db=0) p = r.pubsub() p.subscribe("coderknock", "sanchan", "python") """ # 基於上一個命令的示例,此時在客戶端中執行 coderknock> PUBSUB CHANNELS 1) "python" 2) "blog" 3) "news" 4) "test" 5) "oschina" 6) "coderknock" 7) "sanchan" # 說明訂閱成功 # 統計訂閱數量 coderknock> PUBSUB NUMSUB coderknock news blog oschina test sanchan coderknock.* python 1) "coderknock" 2) (integer) 3 3) "news" 4) (integer) 1 5) "blog" 6) (integer) 1 7) "oschina" 8) (integer) 1 9) "test" 10) (integer) 1 11) "sanchan" 12) (integer) 3 13) "coderknock.*" 14) (integer) 0 15) "python" 16) (integer) 1 """ time.sleep(10) # 休眠 10 秒 p.unsubscribe("sanchan") """ # 此時取消了一個 sanchan 的訂閱 coderknock> PUBSUB NUMSUB coderknock news blog oschina test sanchan coderknock.* python 1) "coderknock" 2) (integer) 3 3) "news" 4) (integer) 1 5) "blog" 6) (integer) 1 7) "oschina" 8) (integer) 1 9) "test" 10) (integer) 1 11) "sanchan" 12) (integer) 2 13) "coderknock.*" 14) (integer) 0 15) "python" 16) (integer) 1 """ time.sleep(10) # 休眠 10 秒 p.unsubscribe() """ # 此時該 python 中訂閱所有退訂 coderknock> PUBSUB NUMSUB coderknock news blog oschina test sanchan coderknock.* python 1) "coderknock" 2) (integer) 2 3) "news" 4) (integer) 1 5) "blog" 6) (integer) 1 7) "oschina" 8) (integer) 1 9) "test" 10) (integer) 1 11) "sanchan" 12) (integer) 2 13) "coderknock.*" 14) (integer) 0 15) "python" 16) (integer) 0 """
#### UNSUBSCRIBE
自2.0.0可用。
時間複雜度:O(N+M) ,其中
N
是客戶端已訂閱的模式的數量,M
則是系統中全部客戶端訂閱的模式的數量。
指示客戶端退訂全部給定模式。
若是沒有模式被指定,也便是,一個無參數的 PUNSUBSCRIBE
調用被執行,那麼客戶端使用 PSUBSCRIBE
命令訂閱的全部模式都會被退訂。在這種狀況下,命令會返回一個信息,告知客戶端全部被退訂的模式
這個命令在不一樣的客戶端中有不一樣的表現。
客戶端在執行訂閱命令以後進入了訂閱狀態,只能接收 SUBSCRIBE
、PSUBSCRIBE
、UNSUBSCRIBE
、PUNSUBSCRIBE
四個命令。
開啓的訂閱客戶端,沒法收到該頻道以前的消息,由於 Redis 不會對發佈的消息進行持久化。
和不少專業的消息隊列系統(例如Kafka、RocketMQ)相比,Redis的發佈訂閱略顯粗糙,例如沒法實現消息堆積和回溯。但勝在足夠簡單,若是當前場景能夠容忍的這些缺點,也不失爲一個不錯的選擇。
聊天室、公告牌、服務之間利用消息解耦均可以使用發佈訂閱模式
本人的直播課程在 7 月份就要開始了,但願小夥伴們支持一下,如今報名有優惠噢