---
# System prepended metadata

title: Redis (三) - Pub/Sub 發佈訂閱
tags: [Redis]

---

# Redis (三) - Pub/Sub 發佈訂閱
Pub/Sub 就是 Publish 和 Subscribe，也就是發佈訂閱。發佈訂閱是一種訊息通訊的模式，發佈者(pub) 傳送訊息，訂閱者(sub) 接收訊息。

<!-- more -->

概念是訂閱者會訂閱一個或多個頻道(channel)，如下圖有三個訂閱者訂閱了頻道 Channel1。

![Subscribe](https://i.imgur.com/s5kAn9t.png)

當有新訊息透過 Publish 命令發送給 Channel1 時，就會被發送給這個頻道的三個訂閱者。

![Publish](https://i.imgur.com/H2tiV5q.png)

所以發佈訂閱並不是針對特定的收件人傳送訊息，發佈者只會把訊息傳送到頻道中，而且發佈者也不會知道誰會收到。收訊息完全取決於訂閱者訂閱哪些頻道，有訂閱該頻道才會收到頻道的訊息。

下面我們就來介紹實作發佈訂閱的指令和方式。

## Pub/Sub 指令
### Subscribe 
Subscribe 用來訂閱頻道，可以一次訂閱多個。
```bash=
127.0.0.1:6379> subscribe <channel1> <channel2> ...
```
### Publish
Publish 可以用來發佈訊息到頻道裡
```bash=
127.0.0.1:6379> publish <channel> <message>
```

### 範例 : 

首先先建立一個訂閱頻道 channel1。
```bash=
127.0.0.1:6379> subscribe channel1
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel1"
3) (integer) 1
```

接著另外再開啟一個 terminal 連線進同一個 Redis，然後在頻道 channel1 發佈訊息。
```bash=
127.0.0.1:6379> publish channel1 helloworld
(integer) 1
```

回到原本的 terminal 可以看到收到了訊息。
```bash=
127.0.0.1:6379> subscribe channel1
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel1"
3) (integer) 1
1) "message"
2) "channel1"
3) "helloworld"
```

### Psubscribe
Psubscribe 可以一次訂閱一個或多個符合指定的 pattern 的頻道。
```bash=
127.0.0.1:6379> psubscribe <pattern1> <pattern2> ...
```

範例 : 
```bash=
127.0.0.1:6379> psubscribe *.news *.sports
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "*.news"
3) (integer) 1
1) "psubscribe"
2) "*.sports"
```

### Pubsub 
Pubsub 用來查看訂閱與發佈系統的狀態。
```bash=
127.0.0.1:6379> pubsub <subcommand> <argument1> <argument2> ...
```
SubCommand 有三個指令可以選擇，如下 : 

**Channels**
Channels 會列出目前活躍的頻道，活躍頻道是指至少有一個訂閱者的頻道。也可以指定 pattern 來列出指定的頻道。
```bash=
127.0.0.1:6379> pubsub <channels> <pattern>
```

**範例 :** 
先建立和訂閱多個頻道
```bash=
127.0.0.1:6379> subscribe taiwan.news taiwan.sports taiwan.weather
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "taiwan.news"
3) (integer) 1
1) "subscribe"
2) "taiwan.sports"
3) (integer) 2
1) "subscribe"
2) "taiwan.weather"
3) (integer) 3
```

再另外開啟一個 Terminal 連進 Redis，就可以用 pubsub channels 指令查看活躍的頻道。
```bash=
127.0.0.1:6379> pubsub channels
1) "taiwan.news"
2) "taiwan.weather"
3) "taiwan.sports"
127.0.0.1:6379> pubsub channels taiwan.*
1) "taiwan.news"
2) "taiwan.weather"
3) "taiwan.sports"
```

**Numsub**
Numsub 可以查看頻道的訂閱者數量。
```bash=
127.0.0.1:6379> pubsub numsub <channel1> <channel2> ...
```

**範例 :**
```bash=
127.0.0.1:6379> pubsub numsub taiwan.news taiwan.sports
1) "taiwan.news"
2) (integer) 1
3) "taiwan.sports"
4) (integer) 1
```

**Numpat**
Numpat 可以查看客戶端訂閱的所有 pattern 總數。Numpat 要搭配 Psubscribe 才有 pattern 可以計算。
```bash=
127.0.0.1:6379> pubsub numpat
```

**範例 :** 
```bash=
// 以下由三個不同的 terminal 作為客戶端分別指定 pattern 訂閱頻道
127.0.0.1:6379> psubscribe *.news *.sports
127.0.0.1:6379> psubscribe *.social
127.0.0.1:6379> psubscribe *.n*

// 輸出的總數 4 代表的是幾種 pattern
127.0.0.1:6379> pubsub numpat
(integer) 4
```

### Unsubscribe
Unsubscribe 用於退訂一個或多個頻道。
```bash=
127.0.0.1:6379> unsubscribe <channel1> <channel2> ...
```

範例 : 
```bash=
127.0.0.1:6379> unsubscribe taiwan.news
1) "unsubscribe"
2) "taiwan.news"
3) (integer) 0
```
### Punsubscribe
Punsubscribe 用於退訂一個或多個符合指定的 pattern 的頻道。
```bash=
redis 127.0.0.1:6379> punsubscribe <pattern1> <pattern2> ...
```

範例 : 
```bash=
127.0.0.1:6379> punsubscribe taiwan.*
1) "punsubscribe"
2) "taiwan.*"
3) (integer) 0
```

## Summary
這一篇介紹了 Redis 支援的發佈訂閱，這是非常實用的功能，可以大幅的提升系統的延展性。想了解更多 Redis 的 Pub/Sub 請參考 [Redis 官網](https://redis.io/topics/pubsub)。

[下一篇](https://tienyulin.github.io/redis-transcation) 將介紹 Redis 的 Transaction，可以一次執行多條指令以提升效能。

## 參考
[1] [Redis 發佈訂閱](https://www.runoob.com/redis/redis-pub-sub.html)
[2] [Redis 命令參考](http://doc.redisfans.com/index.html)

###### tags: `Redis`