redis 发布订阅 场景订阅频道后怎么取消

Redis 教程
Redis 发布订阅 Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。 Redis 客户端可以订阅任意数量的频道。 下图展示了频道 channel1 , 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的关系:
当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端:
实例 以下实例演示了发布订阅是如何工作的。在我们实例中我们创建了订阅频道名为 redisChat:
redis 127.0.0.1:6379& SUBSCRIBE redisChat
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "redisChat"
3) (integer) 1
现在,我们先重新开启个 redis 客户端,然后在同一个频道 redisChat 发布两次消息,订阅者就能接收到消息。
redis 127.0.0.1:6379& PUBLISH redisChat "Redis is a great caching technique"
(integer) 1
redis 127.0.0.1:6379& PUBLISH redisChat "Learn redis by w3cschool.cc"
(integer) 1
# 订阅者的客户端会显示如下消息
1) "message"
2) "redisChat"
3) "Redis is a great caching technique"
1) "message"
2) "redisChat"
3) "Learn redis by w3cschool.cc"
Redis 发布订阅命令 下表列出了 redis 发布订阅常用命令:
序号命令及描述 1 订阅一个或多个符合给定模式的频道。 2 查看订阅与发布系统状态。 3 将信息发送到指定的频道。 4 退订所有给定模式的频道。
5 订阅给定的一个或多个频道的信息。 6 指退订给定的频道。  本系列已经过半了,这一篇我们来看看redis好玩的发布订阅模式,其实在很多的MQ产品中都存在这样的一个模式,我们常听到的一个例子
就是邮件订阅的场景,什么意思呢,也就是说100个人订阅了你的博客,如果博主发表了文章,那么100个人就会同时收到通知邮件,除了这个
场景还能找到其他场景么,当然有啦,你想想,如果你要在内存里面做一个读写分离的程序,为了维持数据的完整性,你是不是需要保证在写入
的时候,也要分发到各个读内存的程序中呢?所以说场景还是很多的,在于你的挖掘~~~ 下面还是从基本命令入手:
一:命令简介
从redis手册上面可以看到,其实&发布、订阅&模式才区区6个命令,下面听我一一解说下哈~~~
1. subscribe
SUBSCRIBE channel [channel ...]
订阅给定的一个或多个频道的信息。
& & &从上面的官方解释上来看,它的玩法有一点像现实生活中我们听收音机一个道理,要想听收音机,我们要做什么?肯定就是调频啦,只有在正
确的频道上面,我们才能听得到好听的节目,所以说subscribe首先要订阅一个频道(channel),下面我举个例子,开两个client,分别订阅着
msg 这个频道,比如下面这样:
& &到现在为止,这两个subscibe都在监视着msg这个频道,接下来,如果msg频道有消息传出,必定会被subscribe接收到,先我们还是看看
redis手册上怎么用这个命令。
PUBLISH channel message
将信息 message 发送到指定的频道 channel 。
看到上面命令的用法,我也就放心了。
看到么有,publish在msg这个频道上面发送消息后,被subscribe监视到了,然后就被分别打印输出了,好了,到现在为止,最基本的发布
订阅模式就是这样,是不是很简单哈。。。其实呢??? 也就是这么简单呐,但是呢,有时候我们还有这样一个需求,就是我能不能模糊匹
配key呢???举了例子,就是要求订阅china为前缀的所有频道,如果这样也可以做到的话,那确实是很牛逼啦。。。我要是回答的话,当
然啦,强大的redis自然会做到这一点,它提供了的命令就是:Psubscribe。
3. Psubscribe
PSUBSCRIBE pattern [pattern ...]
订阅一个或多个符合给定模式的频道。
每个模式以 * 作为匹配符,比如 it* 匹配所有以 it 开头的频道( it.news 、 it.blog 、 it.tweets 等等), news.* 匹配所有以 news. 开头的频道( news.it 、 news.global.today 等等),诸如此类。
看到上面的解释,你心里可能就在想,这不就是正则匹配么。。。而且前缀&P&就是Pattern的意思,对吧,接下来我就订阅一下所有china为
前缀的channel。
好了,最常用的也就是这三个命令,接下来我们简单分析一下代码。
二: 源码简单分析
  其实redis的发布订阅模式,使用RedisServer下面的&pubsub_channels字典 和&pubsub_patterns数组存放的,所有的操作代码都
在pubsub.c文件下,如下图:
1. &&pubsub_channels&
& & & 可以看到,它是一个字典结构,通过注释你应该明白,它的key为channel,value为list。
2. &&pubsub_patterns
& & & 同样从注释中,你可以看到,其实它就是存放模式匹配的subscribe的clients列表,对吧,用一个list数组实现。
3. & subcribeCommand
& & & 通过下面的代码,你是不是在脑子里面很有轮廓了???其实这个pubsub_channels果然就是key=channel,value=list的存放模式,
这个list就是所谓的clients列表,这样的话,你就知道了哪些key挂了哪些clients,对吧,如果再publish的话,只需要遍历一下这个list就知
道结果了。
4. &publishCommand
  先前也说了,publish的原理很简单,就是找到字典中的channel这个key,获取到clients之后,遍历client的来发送信息。
同样的道理,pubsub_patterns也是差不多的实现,只要大家简单看一下pubsub.c这个源代码文件,差不多都会懂得,没啥好说的,
希望这篇对你有用~
阅读(...) 评论()redis发布订阅
当前位置:
>> redis发布订阅
redis发布订阅
redis发布订阅实例代码教程-
发布订阅(pub/sub)是一种消息通信模式,主要的目的是解耦消息发布者和消息订阅者之间的耦合,这点和设计模式中的观察者模式比较相似。
&发布订阅(pub/sub)是一种消息通信模式,主要的目的是解耦消息发布者和消息订阅者之间的耦合,这点和设计模式中的观察者模式比较相似。pub&/sub不仅仅解决发布者和订阅者直接代码级别耦合也解决两者在物理部署上的耦合。作为一个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&=&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"
news.share
--------------------------------------
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&"
(integer)&2&
redis&&publish&news.blog&"I&post&a&blog"
(integer)&2
4.查看两个订阅client的输出
此时java&client打印如下内容
news.share
share&a&link&
--------------------------------------
I&post&a&blog
--------------------------------------
另一个redis-cli输出如下
1.&"pmessage"
2.&"news.*"
3.&"news.share"
4.&"share&a&link&"
1.&"pmessage"
2.&"news.*"
3.&"news.blog"
4.&"I&post&a&blog"
java&client使用subscribe命令订阅news.share和news.blog两个通道,然后立即收到server返回的订阅成功消息,可以看出&redis的协议是文本类型的,这里不解释具体协议内容了,可以参考或者。这个报文内容有两部分,第一部分表示该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行代码)。在安全,认证,可靠性这方便都没有太多支持。redis为什么总是把订阅/发布和消息队列联系在一起?很迷惑,求解释~ - 开源中国社区
当前访客身份:游客 [
当前位置:
是这样,消息队列负责存储一些信息,然后用来持久化到数据库,主要用来解决高并发下减轻数据库的压力以及解决线程阻塞问题,而redis的pub/sub功能主要用来发布和订阅消息,而且消息是瞬时的,实在想象不到它和队列有什么关系。。现在假设我要解决一个抢红包的高并发的问题,我只需要让点击红包的用户存进redis的一个list里面,然后单开一个线程不断从list中读取数据进行持久化就行了,这样实现了队列功能,也解决了线程阻塞和数据库压力问题,和消息的发布订阅也没什么关系啊,难道是我理解有误?如果是这样,请大神指点,就以抢红包大并发为例,谢谢!
共有2个答案
<span class="a_vote_num" id="a_vote_num_
这里边你所谓的单独起一个线程,实际上实现的就是监听嘛,消息发布者实际就是你在往队列里面压数据,而消息订阅者就是你写的线程来读取。
所以,这里面,队列是一种数据结构,而你所说的发布者/订阅者其实就是想要做的事的一种模式,通过队列来进行存储实现了,也不一定非用队列的,用SortSet进行值排序,一样可以称之为队列。
<span class="a_vote_num" id="a_vote_num_
不知道LZ是在哪看到把发布/订阅和消息队列联系在一起的。
redis的发布/订阅, 是一种消息通信模式,一般可以用于及时通信系统,比如聊天室,实时提醒。主要是为了解耦消息发布者和消息订阅者之间的耦合。
就像你说的消息是瞬时的,来一个就要处理一个,在大并发下,并没有解决线程堵塞和数据库压力问题。
如果简单的消息队列,可以用redis的list结构处理,&&& 或者选用专门的像rabbitmq等这样的
以上,纯属个人理解,有问题请告诉我,,,
--- 共有 5 条评论 ---
: 嗯嗯,,这几天看看能写个demo不,感觉有点无从下手,那个处理程序应该写在哪里,会不会随着tomcat的启动就开始运行?您有demo没有?有的话私信一下~谢谢你这么耐心~
(9个月前)&nbsp&
: 既然要监控队列,后台肯定有个消费队列的程序运行,抢红包这样非常要求实时性的可以使用 POP的堵塞版本 BPOP,那样就会等到有元素时才继续执行, 也可以设置超时时间。
(9个月前)&nbsp&
: 嗯嗯,开辟线程专门用来读取redis队列,这样做的话线程池中的程序就得不停的进行下去,这样真的好吗?还是有更好些的办法?
(9个月前)&nbsp&
: 没啥问题,通过push 和pop来取list中的数据,一般是LPUSH RPOP,通过先进先出的顺序
(9个月前)&nbsp&
嗯嗯,谢谢您的回答,我也是刚刚接触,昨天写了个pub/sub的小demo,感觉和队列没什么关系,那么你看我上面关于队列的理解有偏差没?是靠线程池进行处理队列的吗?
(9个月前)&nbsp&
更多开发者职位上
有什么技术问题吗?
上帝爱众生的其它问题
类似的话题}

我要回帖

更多关于 redis消息订阅与发布 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信