Redis 發佈訂閱

簡介

Redis提供了基於「發佈/訂閱」模式的消息機制,此種模式下,消息發佈者和訂閱者不進行直接通訊,發佈者客戶端向指定的頻道(channel)發佈消息,訂閱該頻道的每一個客戶端均可以收到該消息(頻道沒有」建立「的概念,能夠直接訂閱、亦可直接發佈消息)。python

命令

發佈消息

PUBLISH

自2.0.0可用。redis

時間複雜度:O(N+M),其中 N 是頻道 channel 的訂閱者數量,而 M 則是使用模式訂閱(subscribed patterns)的客戶端的數量。shell

語法:PUBLISH channel message
說明:

將信息 message 發送到指定的頻道 channelsegmentfault

返回值:

接收到信息 message 的訂閱者數量。測試

示例:
# 向沒有訂閱者的頻道發送信息
coderknock> PUBLISH new_channel "test publish"
(integer) 0
# 向有訂閱者的頻道發送信息
coderknock>  PUBLISH channel1 "new channel1"
(integer) 1

訂閱

SUBSCRIBE

自2.0.0可用。ui

時間複雜度:O(N),其中 N 是訂閱的頻道的數量。命令行

語法:SUBSCRIBE channel [channel ...]
說明:

訂閱給定的一個或多個頻道的信息。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 是訂閱的模式的數量。

語法:PSUBSCRIBE pattern [pattern ...]
說明:

訂閱一個或多個符合給定模式的頻道。

每一個模式以 * 做爲匹配符,好比 it* 匹配全部以 it 開頭的頻道( it.newsit.blogit.tweets 等等), news.* 匹配全部以 news. 開頭的頻道( news.itnews.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 subcommand [argument [argument ...]]
說明:

PUBSUB 是一個查看訂閱與發佈系統狀態的內省命令, 它由數個不一樣格式的子命令組成, 如下將分別對這些子命令進行介紹。

PUBSUB CHANNELS [pattern]

說明:

列出當前的活躍頻道。

活躍頻道指的是那些至少有一個訂閱者的頻道, 訂閱模式的客戶端不計算在內。

pattern 參數是可選的:

  • 若是不給出 pattern 參數,那麼列出訂閱與發佈系統中的全部活躍頻道。

  • 若是給出 pattern 參數,那麼只列出和給定模式 pattern 相匹配的那些活躍頻道。

複雜度: O(N) , 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)

PUBSUB NUMSUB [channel-1 ... channel-N]

說明:

返回給定頻道的訂閱者數量, 訂閱模式的客戶端不計算在內。

複雜度:O(N) , N 爲給定頻道的數量。
返回值: 一個多條批量回復(Multi-bulk reply),回覆中包含給定的頻道,以及頻道的訂閱者數量。 格式爲:頻道 channel-1channel-1 的訂閱者數量,頻道 channel-2channel-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

PUBSUB NUMPAT

說明:

返回 訂閱模式 的數量。

注意, 這個命令返回的不是訂閱模式的客戶端的數量, 而是客戶端訂閱的全部模式的數量總和。

複雜度:O(N) , N 爲給定頻道的數量。
返回值: 一個整數回覆(Integer reply)。
示例:
#採用上面示例中的訂閱客戶端,這裏統計的 訂閱模式 包含 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 [channel [channel ...]]
說明:

指示客戶端退訂給定的頻道。

若是沒有頻道被指定,也便是,一個無參數的 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 [pattern [pattern ...]]
說明:

指示客戶端退訂全部給定模式。

若是沒有模式被指定,也便是,一個無參數的 PUNSUBSCRIBE 調用被執行,那麼客戶端使用 PSUBSCRIBE 命令訂閱的全部模式都會被退訂。在這種狀況下,命令會返回一個信息,告知客戶端全部被退訂的模式

返回值:

這個命令在不一樣的客戶端中有不一樣的表現。

有關訂閱命令有兩點須要注意:

  • 客戶端在執行訂閱命令以後進入了訂閱狀態,只能接收 SUBSCRIBEPSUBSCRIBEUNSUBSCRIBEPUNSUBSCRIBE 四個命令。

  • 開啓的訂閱客戶端,沒法收到該頻道以前的消息,由於 Redis 不會對發佈的消息進行持久化。

和不少專業的消息隊列系統(例如Kafka、RocketMQ)相比,Redis的發佈訂閱略顯粗糙,例如沒法實現消息堆積和回溯。但勝在足夠簡單,若是當前場景能夠容忍的這些缺點,也不失爲一個不錯的選擇。

使用場景

聊天室、公告牌、服務之間利用消息解耦均可以使用發佈訂閱模式

我是廣告

本人的直播課程在 7 月份就要開始了,但願小夥伴們支持一下,如今報名有優惠噢

https://segmentfault.com/l/15...

https://segmentfault.com/l/15...

相關文章
相關標籤/搜索