数据库

 首页 > 数据库 > Redis > redis发布订阅(pub/sub)是一种消息通信模式

redis发布订阅(pub/sub)是一种消息通信模式

分享到:
【字体:

  发布订阅(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]+"rn"; try {
 Socket 
socket = new Socket("192.168.56.55",6379);
 
InputStream in = 
socket.getInputStream();
 
OutputStream out = socket.getOutputStream();
 
out.write(cmd.getBytes()); //发送订阅命令 byte[] buffer = new byte[1024]; while (true) 
{ int readCount = 
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 "subscribe 
news.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 link http://www.google.com" (integer) 2
redis> publish 
news.blog "I post a blog"
(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行代码)。在安全,认证,可靠性这方便都没有太多支持。
分享到:
phpredisclient稳定性测试
一直有个想法,做一个只有redis作数据库的系统,一直对redis的功能比较赞赏,但不知道redis的单线程稳定性如何,之前测试过100万Key的写入锁,今天又测试了一下正常读写下redis cli的get稳定性。 结果看起来还可以,2万次左右的单次读取锁0.001秒,如果每次展示需要读取300次cache,整体来说,在redis上的时间损...
redis主从复制配置和使用都非常简单
  redis主从复制配置和使用都非常简单。通过主从复制可以允许多个slave server拥有和master server相同的数据库副本。下面是关于redis主从复制的一些特点 1.master可以有多个slave 2.除了多个slave连到相同的master外,slave也可以连接其他slave形成图状结构 3.主从复制不会阻塞master。也就是说当一个或多个slave与master...
  •         php迷,一个php技术的分享社区,专属您自己的技术摘抄本、收藏夹。
  • 在这里……