如何在 Golang 中使用 Redis 訂閱/發布
訂閱,取消訂閱和發布實現了發布/訂閱消息范式(引自wikipedia),發送者(發布者)不是計划發送消息給特定的接收者(訂閱者)。而是發布的消息分到不同的頻道,不需要知道什么樣的訂閱者訂閱。訂閱者對一個或多個頻道感興趣,只需接收感興趣的消息,不需要知道什么樣的發布者發布的。這種發布者和訂閱者的解耦合可以帶來更大的擴展性和更加動態的網絡拓撲。
什么是 Redis 訂閱發布?
Redis 的 訂閱(SUBSCRIBE) 可以讓客戶端訂閱任意數量的頻道, 每當有新信息發送到被訂閱的頻道時, 信息就會被發送給所有訂閱指定頻道的客戶端。
如圖例子
訂閱:
舉個例子,假設 客戶端 A、B、C 訂閱了一個 channel 通道。那么他講阻塞 等待接收信息。等到有一個新的消息 往 channel 里面發送數據。那么通道將會 通知給客戶端 A、B、C
發布:
redis-client 實驗訂閱發布
1、首先開啟 Redis
2、打開三個 redis-cli 窗口
我們可以看到當你訂閱后,會阻塞在這里,等待新信息
3、在新的redis-cli 窗口 PUBLISH 一個新的信息 Channel 信息
4、切換窗口,我們可以看到另外兩個訂閱的窗口接受到了一條 channel 信息
查看訂閱者的總數
這里有兩個窗口訂閱了消息,所以就有 2
訂閱發布適合什么場景?
訂閱發布的好處是,訂閱接受的信息只會發送給訂閱者。
假設我有一個系統,我有 a,b 兩個訂閱的通道。
我在某個服務中,只需要訂閱 a 信息,那么用 Redis 的訂閱 / 發布,訂閱者只會接受到他需要接受的訂閱信息。
簡單的應用場景的話, 以門戶網站為例, 當編輯更新了某推薦板塊的內容后:
CMS發布清除緩存的消息到channel (推送者推送消息)
門戶網站的緩存系統通過channel收到清除緩存的消息 (訂閱者收到消息),更新了推薦板塊的緩存。
下面我會用列子來解釋,我如何在 Golang 中使用訂閱發布來關閉某些服務
在 Golang 中使用訂閱發布
1、 下載 go redis 庫
go get -u github.com/go-redis/redis
2、鏈接Redis 並且 訂閱 wait-close服務
package main
import (
"fmt"
"log"
"sync"
example "github.com/yoloyi/redis-example"
)
func main() {
var wg sync.WaitGroup
// 這里我們用攜程來模擬多個服務
for i := 0; i < 2; i++ {
wg.Add(1)
go func(i int) {
client := example.InitRedis()
pb := client.Subscribe("wait-close")
fmt.Println("阻塞,等待讀取 Channel 信息")
for {
select {
case mg := <-pb.Channel():
// 等待從 channel 中發布 close 關閉服務
if mg.Payload == "close" {
// 當
wg.Done()
} else {
log.Println("接channel信息", mg.Payload)
}
default:
}
}
}(i)
}
wg.Wait()
log.Println("結束 channel")
}
3、打開服務
4、從 redis-cli 或者其他客戶端發布信息
PUBLISH wait-close new_message
5、當我們發布了 close 給某個通道,我們可以看到 兩個訂閱都被關閉了。
PUBLISH wait-close close
結尾
這里的例子,用了兩個協程來做兩個服務,實際的應用場景中,我們在分布式系統中,每一個服務里面都會訂閱這樣一個類似的通道,比如更新 LocalCache。當用戶在前台修改了某個值,我們需要去更新你服務里面保存的一些值,就可以通過這種方式去觸發到不同的機器。來更新一些緩存啊,或者是一些其他信息。
有一些其他類似的隊列,比如 ActiveMQ 也提供了類似的 發布 / 訂閱 的功能,但是在 ActiveMQ 要遠比 Redis更復雜,因為 Redis 是一個 Cache,畢竟Redis不是專門做發布訂閱的。但是如果系統中已經有了Redis,並且需要基本的發布訂閱功能,就沒有必要再安裝ActiveMQ了,
具體選型,看你領導。