原文連接html
訂閱,取消訂閱和發佈實現了發佈/訂閱消息範式(引自wikipedia),發送者(發佈者)不是計劃發送消息給特定的接收者(訂閱者)。而是發佈的消息分到不一樣的頻道,不須要知道什麼樣的訂閱者訂閱。訂閱者對一個或多個頻道感興趣,只需接收感興趣的消息,不須要知道什麼樣的發佈者發佈的。這種發佈者和訂閱者的解耦合能夠帶來更大的擴展性和更加動態的網絡拓撲。git
Redis 的 訂閱(SUBSCRIBE) 可讓客戶端訂閱任意數量的頻道, 每當有新信息發送到被訂閱的頻道時, 信息就會被髮送給全部訂閱指定頻道的客戶端。github
如圖例子golang
訂閱:redis
舉個例子,假設 客戶端 A、B、C 訂閱了一個 channel 通道。那麼他講阻塞 等待接收信息。等到有一個新的消息 往 channel 裏面發送數據。那麼通道將會 通知給客戶端 A、B、C緩存
發佈:網絡
redis-client 實驗訂閱發佈分佈式
一、首先開啓 Redis網站
二、打開三個 redis-cli 窗口spa
咱們能夠看到當你訂閱後,會阻塞在這裏,等待新信息
三、在新的redis-cli 窗口 PUBLISH 一個新的信息 Channel 信息
四、切換窗口,咱們能夠看到另外兩個訂閱的窗口接受到了一條 channel 信息
查看訂閱者的總數
這裏有兩個窗口訂閱了消息,因此就有 2
訂閱發佈的好處是,訂閱接受的信息只會發送給訂閱者。
假設我有一個系統,我有 a,b 兩個訂閱的通道。
我在某個服務中,只須要訂閱 a 信息,那麼用 Redis 的訂閱 / 發佈,訂閱者只會接受到他須要接受的訂閱信息。
簡單的應用場景的話, 以門戶網站爲例, 當編輯更新了某推薦板塊的內容後:
CMS發佈清除緩存的消息到channel (推送者推送消息)
門戶網站的緩存系統經過channel收到清除緩存的消息 (訂閱者收到消息),更新了推薦板塊的緩存。
下面我會用列子來解釋,我如何在 Golang 中使用訂閱發佈來關閉某些服務
一、 下載 go redis 庫
go get -u github.com/go-redis/redis
二、連接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") }
三、打開服務
四、從 redis-cli 或者其餘客戶端發佈信息
PUBLISH wait-close new_message
五、當咱們發佈了 close 給某個通道,咱們能夠看到 兩個訂閱都被關閉了。
PUBLISH wait-close close
這裏的例子,用了兩個協程來作兩個服務,實際的應用場景中,咱們在分佈式系統中,每個服務裏面都會訂閱這樣一個相似的通道,好比更新 LocalCache。當用戶在前臺修改了某個值,咱們須要去更新你服務裏面保存的一些值,就能夠經過這種方式去觸發到不一樣的機器。來更新一些緩存啊,或者是一些其餘信息。
有一些其餘相似的隊列,好比 ActiveMQ 也提供了相似的 發佈 / 訂閱 的功能,可是在 ActiveMQ 要遠比 Redis更復雜,由於 Redis 是一個 Cache,畢竟Redis不是專門作發佈訂閱的。可是若是系統中已經有了Redis,而且須要基本的發佈訂閱功能,就沒有必要再安裝ActiveMQ了,
具體選型,看你領導。