redis學習筆記之發佈訂閱

發佈訂閱(pub/sub)是一種消息通信模式,主要的目的是解耦消息發佈者和消息訂閱者之間的耦合,這點和設計模式中的觀察者模式比較相似。pub /sub不僅僅解決發佈者和訂閱者直接代碼級別耦合也解決兩者在物理部署上的耦合。redis作爲一個pub/sub server,在訂閱者和發佈者之間起到了消息路由的功能。訂閱者可以通過subscribe和psubscribe命令向redis server訂閱自己感興趣的消息類型,redis將消息類型稱爲通道(channel)。當發佈者通過publish命令向redis server發送特定類型的消息時。訂閱該消息類型的全部client都會收到此消息。這裏消息的傳遞是多對多的。一個client可以訂閱多個 channel,也可以向多個channel發送消息。

下面做個實驗。這裏使用兩個不同的client一個是redis自帶的redis-cli另一個是用java寫的簡單的client。代碼如下
import java.net.*;
import java.io.*;
public class PubSubTest {
    public static void main(String[] args) {
        String cmd = args[0]+"\r\n";
        try {
            Socket socket = newSocket("192.168.56.55",6379);
            InputStream in =socket.getInputStream();
            OutputStream out =socket.getOutputStream();
            out.write(cmd.getBytes());  //發送訂閱命令
            byte[] buffer = newbyte[1024];
            while (true) {
                intreadCount =    in.read(buffer);
               System.out.write(buffer, 0, readCount);
               System.out.println("--------------------------------------");
            }
        } catch (Exception e) {
        }
    }
}

代碼就是簡單的從命令行讀取傳過來的訂閱命令,然後通過一個socket連接發送給redis server,然後進入while循環一直讀取redis server傳過來訂閱的消息。並打印到控制檯

1 首先編譯並運行此java程序(我是win7下面運行的)
D:\>javac PubSubTest.java
D:\>java PubSubTest "subscribenews.share news.blog"
*3
$9
subscribe
$10
news.share
:1

*3
$9
subscribe
$9
news.blog
:2
--------------------------------------
2 啓動redis-cli
redis> psubscribe news.*
Reading messages... (press Ctrl-c to quit)
1. "psubscribe"
2. "news.*"
3. (integer) 1 

3 再啓動一個redis-cli用來發布兩條消息
redis> publish news.share "share a linkhttp://www.google.com"
(integer) 2 
redis> publish news.blog "I post ablog"
(integer) 2

4.查看兩個訂閱client的輸出
此時java client打印如下內容
*3
$7
message
$10
news.share
$34
share a link http://www.google.com
--------------------------------------
*3
$7
message
$9
news.blog
$13
I post a blog
--------------------------------------
另一個redis-cli輸出如下
1. "pmessage"
2. "news.*"
3. "news.share"
4. "share a link http://www.google.com"

1. "pmessage"
2. "news.*"
3. "news.blog"
4. "I post a blog"


分析下
java client使用subscribe命令訂閱news.share和news.blog兩個通道,然後立即收到server返回的訂閱成功消息,可以看出 redis的協議是文本類型的,這裏不解釋具體協議內容了,可以參考http://redis.io/topics/protocol或者http://terrylee.me/blog/post/2011/01/26/redis-internal-part3.aspx。這個報文內容有兩部分,第一部分表示該socket連接上使用 subscribe訂閱news.share成功後,此連接訂閱通道數爲1,後一部分表示使用subscribe訂閱news.blog成功後,該連接訂 閱通道總數爲2。

redis client使用psubscribe訂閱了一個使用通配符的通道(*表示任意字符串),此訂閱會收到所有與news.*匹配的通道消息。redis- cli打印到控制檯的訂閱成功消息表示使用psubscribe命令訂閱news.*成功後,連接訂閱通道總數爲1。

當我們在一個client使用publish 向news.share和news.blog通道發出兩個消息後。redis返回的(integer) 2表示有兩個連接收到了此消息。通過觀察兩個訂閱者的輸出可以驗證。具體格式不解釋了,都比較簡單。

看 完一個小例子後應該對pub/sub功能有了一個感性的認識。需要注意的是當一個連接通過subscribe或者psubscribe訂閱通道後就進入訂 閱模式。在這種模式除了再訂閱額外的通道或者用unsubscribe或者punsubscribe命令退出訂閱模式,就不能再發送其他命令。另外使用 psubscribe命令訂閱多個通配符通道,如果一個消息匹配上了多個通道模式的話,會多次收到同一個消息。

jredis目前版本沒提供pub/sub支持,不過自己實現一個應該也挺簡單的。整個應用程序可以共享同一個連接。因爲redis返回的消息報文中除了消息內容本身外還包括消息相關的通道信息,當收到消息後可以根據不同的通道信息去調用不同的callback來處理。

另外個人覺得redis的pub/sub還是有點太單薄(實現才用150行代碼)。在安全,認證,可靠性這方便都沒有太多支持。

更多精彩內容請關注:http://bbs.superwu.cn 

關注超人學院微信二維碼:

關注超人學院java免費學習交流羣:


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章