發布訂閱(pub/sub)是一種訊息通訊模式,主要的目的是解耦訊息發行者和訊息訂閱者之間的
耦合,這點和設計模式中的觀察者模式比較相似。pub/sub 不僅僅解決發行者和訂閱者直接
代碼層級耦合也解決兩者在物理部署上的耦合。redis 作為一個pub/sub 的server,在訂閱者
和發行者之間起到了訊息路由的功能。訂閱者可以通過subscribe 和psubscribe 命令向redis
server 訂閱自己感興趣的訊息類型,redis 將訊息類型稱為通道(channel)。當發行者通過
publish 命令向redis server 發送特定類型的訊息時。訂閱該訊息類型的全部client 都會收到
此訊息。這裡訊息的傳遞是多對多的。一個client 可以訂閱多個channel,也可以向多個channel
發送訊息。
下面做個實驗。這裡使用3 不同的client, client1 用於訂閱tv1 這個channel 的訊息,client2
用於訂閱tv1 和tv2 這2 個chanel 的訊息,client3 用於發布tv1 和tv2 的訊息。
Client1:
650) this.width=650;" title="QQ20131214203048.png" src="http://www.bkjia.com/uploads/allimg/131229/22131I0J-0.png" alt="212155349.png" />
Client2:
650) this.width=650;" title="QQ20131214203048.png" src="http://www.bkjia.com/uploads/allimg/131229/22131I011-1.png" alt="212226969.png" />
Client3:
650) this.width=650;" title="QQ20131214203048.png" src="http://www.bkjia.com/uploads/allimg/131229/22131K410-2.png" alt="212314958.png" />
下面看Client1和Client2的接收情況:
650) this.width=650;" title="QQ20131214203048.png" src="http://www.bkjia.com/uploads/allimg/131229/22131La5-3.png" alt="212435865.png" />
650) this.width=650;" title="QQ20131214203048.png" src="http://www.bkjia.com/uploads/allimg/131229/22131LX3-4.png" alt="212504435.png" />
Client1和Client2都收到了tv1的訊息,然後我們再使用Client3發布一條訊息:
650) this.width=650;" title="QQ20131214203048.png" src="http://www.bkjia.com/uploads/allimg/131229/22131K5F-5.png" alt="212623854.png" />
看看Clien1,Client2的接收情況
650) this.width=650;" title="QQ20131214203048.png" src="http://www.bkjia.com/uploads/allimg/131229/22131M0T-6.png" alt="212728278.png" />
650) this.width=650;" title="QQ20131214203048.png" src="http://www.bkjia.com/uploads/allimg/131229/22131K946-7.png" alt="212801287.png" />
下面將詳細的解釋一下上面的例子
1、client1 訂閱了tv1 這個channel 這個頻道的訊息,client2 訂閱了tv1 和tv2 這2 個頻道的
訊息
2、client3 是用於發布tv1 和tv2 這2 個頻道的訊息發行者
3、接下來我們在client3 發布了一條訊息”publish tv1 program1”,大家可以看到這條訊息是
發往tv1 這個頻道的
4、理所當然的client1 和client2 都接收到了這個頻道的訊息
5、 然後client3 又發布了一條訊息”publish tv2 program2”,這條訊息是發往tv2 的,由於
client1 並沒有訂閱tv1,所以client1 的結果中並沒有顯示出任何結果,但client2 訂閱了這個
頻道,所以client2 是會有返回結果的。
我們也可以用psubscribe tv*的方式批量訂閱以tv 開頭的頻道的內容。
看完這個小例子後應該對pub/sub 功能有了一個感性的認識。需要注意的是當一個串連通過
subscribe 或者psubscribe 訂閱通道後就進入訂閱模式。在這種模式除了再訂閱額外的通道或
者用unsubscribe 或者punsubscribe 命令退出訂閱模式,就不能再發送其他命令。另外使用
psubscribe 命令訂閱多個萬用字元通道,如果一個訊息匹配上了多個通道模式的話,會多次收
到同一個訊息。
Pipeline 批量發送請求
redis 是一個cs 模式的tcp server,使用和http 類似的請求響應協議。一個client 可以通過一
個socket 串連發起多個請求命令。每個請求命令發出後client 通常會阻塞並等待redis 服務
處理,redis 處理完後請求命令後會將結果通過響應報文返回給client。基本的通訊過程如下:
Client: INCR XServer: 1Client: INCR XServer: 2Client: INCR XServer: 3Client: INCR XServer: 4
基本上四個命令需要8 個tcp 報文才能完成。由於通訊會有網路延遲,假如從client 和server
之間的包傳輸時間需要0.125 秒。那麼上面的四個命令8 個報文至少會需要1 秒才能完成。
這樣即使redis 每秒能處理100 個命令,而我們的client 也只能一秒鐘發出四個命令。這顯
示沒有充分利用redis 的處理能力,怎麼樣解決這個問題呢? 我們可以利用pipeline 的方式
從client 打包多條命令一起發出,不需要等待單條命令的響應返回,而redis 服務端會處理
完多條命令後會將多條命令的處理結果打包到一起返回給用戶端。通訊過程如下
Client: INCR XClient: INCR XClient: INCR XClient: INCR XServer: 1Server: 2Server: 3Server: 4
假設不會因為tcp 報文過長而被拆分。可能兩個tcp 報文就能完成四條命令,client 可以將四
個incr 命令放到一個tcp 報文一起發送,server 則可以將四條命令的處理結果放到一個tcp
報文返回。通過pipeline 方式當有大批量的操作時候,我們可以節省很多原來浪費在網路延
遲的時間,需要注意到是用pipeline 方式打包命令發送,redis 必須在處理完所有命令前先緩
存起所有命令的處理結果。打包的命令越多,緩衝消耗記憶體也越多。所以並不是打包的命令
越多越好。具體多少合適需要根據具體情況測試。
具體是否使用pipeline 必須要基於大家手中的
網路情況來決定,不能一切都按最新最好的技術來實施,因為它有可能不是最適合你的。
本文出自 “phper-每天一點點~” 部落格,請務必保留此出處http://janephp.blog.51cto.com/4439680/1340466