redis 发布订阅

发布订阅模式:一个发布者多个订阅者只要选择订阅这个发布者,发布者发布的数据都可以被订阅到,只有订阅者开始订阅之后,发布的数据才可以接收,也就是说历史数据不能接收

127.0.0.1:6379> PUBLISH 163 hello
(integer) 0
127.0.0.1:6379> PUBLISH 163 helloa
(integer) 1
127.0.0.1:6379> PUBLISH 163 helloa1
(integer) 1
127.0.0.1:6379>
127.0.0.1:6379> SUBSCRIBE 163
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "163"
3) (integer) 1
1) "message"
2) "163"
3) "helloa"
1) "message"
2) "163"
3) "helloa1"

127.0.0.1:6379> SUBSCRIBE 163
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "163"
3) (integer) 1
1) "message"
2) "163"
3) "helloa122222"

发布订阅模式使用场景

使用 QQ的时候,或者使用你们腾讯课堂的时候,明白吧?有这么一个现象,尤其使用QQ,它除了我进入课堂、进入聊天室,能够看到新的消息,我往上滑动的时候还能怎
么样,是不是还能拿到之前的消息。来把这个事刷一下?你是不是微信的时候点开之后,
是不是还能看历史的聊天记录,一直往上倒对不对?
那么如果作为一个系统架构,你再驾驭整个项目的时候,到底一个群或者一个聊天室里的消息,把这些的所有的数据从最新的到过往所有的,放到什么地方去存呢?是放到关型数据库呢?还是像放到Rides里呢?比如说就是微信的群,过去10天的、20天的、或一年的聊天记录,是要都放到redis里呢?还是都放到数据库?那么如果都放到数据库的话,那么数据全量可以保证,但是多人查的时候,微信要支撑那么多群,那么多人,那么查询以及翻页的等等系列事情,成本就比较高。
没错,那么这时候我们就把思路扩展一下,因为你现在学了redis了。首先可以做这么
一件事情,我们画一张图,去思考,如果作为客户端的你有几个时态,第一个就是实时性
的,你需要实时的,只要有消息了,就立刻给你,你需要实时性的来获得大家现在每时每
刻在聊什么。另外一个就是你还有一个需求,就是看一些历史性的,然后在看历史性的消
息的时候,其实还有这么一个概念,我们一般人都会去或多或少看历史,但是看历史分为
不同的。你是看两三天的?还是看一两周、两三个月的?
比如说三天之内,或者更老的,基本上是这么一个流程,如果你是产品经理,你在设计微信也好,设计QQ聊天的时候,你会发现用户基本是这么一个流程。第一步它肯定是实时接收到大家所有聊天记录,然后他也会上滑延伸,然后弹出一些历史,然后一般人都停留在三天之内的,再往前他可能不翻了,但是还有一小部分人可能要查一些更老的一些聊天的内容的时候,他可能要再继续翻、再去翻、继续滑,这时候可能触发更老的数据了。那么这个时候数据全量一定是在数据库里,但是用户所有的请求,所有的数据的到达,如果都是从数据库来完成的话,那么用户这么大群体这么多聊天的群,所以对数据库的压力是特别大的,所以一般我们会选择拿Rides做缓存对不对?
这是Rides做缓存的本意,在大部分场景,缓存的目的是更倾向于多数缓存是要解决数
据库的读的请求,把热数据拿过来,有一些也会解决一些写的请求,但是一旦触发写的时
候,后边跟你讲双写的复杂性,所以一般会把那些个数据完整性不是特别强的,直接就搬
到redis作为数据库,存那些实时在写的数据,比如详情页里一个所有的浏览数、购买数、
收藏数,那些数其时,少个几个、10个的,数据稍微不一致也无所谓,能接受,对于企业
来说,所以概念和维度是不一样的,千万不要因为你非得要让他达到一个什么水平儿,而
去逆了一个技术特征,因为Rides它要求的就是快,简单的知识的一个层次的铺垫,大家都
能听懂,那么接下来就是如何设计redis,拿着你学完的知识,覆盖到这三个范围。
把之前学的我们都回忆起来,首先实时的可以用Rides当中的什么东西来实现?实时性聊天的东西,有人发的别人就啪就收到了,可以用刚讲完的分布、订阅?对不对?实时性的来自于这种发布和订阅就可以解决了。
那么请问三天之内的数据和更老的历史的数据,这两个里边更老的一定是来自于数据库,因为到这个环节的时候请求量已经变得很低了。那么请问三天之内的数据要怎么做?
这个窗口三天的,怎么去做这个事情?可以用谁?你们直接学的哪个value的类型可以解决
这个问题?而且消息你拿到3000个历史的数据的时候,这些消息是不是按照他当时发的那
个时间,有序的排好,对不对?注意你是拿数据,你是拿数据,你最终是要给用户窗口里
边刷出这个时间里的记录,他怎么去做这件事情,三天的数据应该怎么做,如果只有redis
的话,好。而且还有什么东西阿?而且可以做窗口的控制,没错,用sorted set。
有序集合,就是你用一个Rides如何驾驭你公司的客户端和你整个项目交接的这三种行为,你用Rides加数据库可以做这件事情,那么回忆一下,这就把你知识要活学活用,有的时候我们知识不是学完了就完了,你也不是要等着去考试的。sorted set当中,然后这里面会
有一个zremrangebyrank 和zremrangebyscore的操作, 有这么两个选项,一个是根据所有排名,也就是就给出一个范围,删除多少,然后它有正向的就有反向的。其实如果保存三天、最近三天的话,其实就是把日期更大的移除,对不对?把日期最小的,比如1号、2号、3号、4号、5号,那么543的三天的数据是要留存在Rides里,然后2号1号这样的数据是要从Rides清除掉,可以去数据库去取,那么你应该留下的是大的,删的是小天数的,所以正向就可以了。因为Rides它内存里边是由小到大排列呢?那么如果使用sorted set的时候,你这边要怎么放?是不要把时间做为你记录的分值,把你用户发的消息直接作为元素是不是可以
了?放进sorted set的时候是不是就已经排好序了?其实你只需要在sorted set当中,维护一个小???圈,你要么就留多少条记录,要么就是按照一个时间去删除更早的或者就是留够
从-1~-50,就留50条在内存里边,不管怎么样,你会留一个窗口在redis内存当中,好吧?
刚说是取数,刚说出去的方向,你有一个客户端是会取,然后客户端是不是它还会往系统中带来数据对不对?带来的数据这里面是不是会有我的缓存,以及里边还分为实时发布和有序的集合,然后发进去就得让别人知道,然后这边你如果一个客户端发消息,肯定是往发布、订阅上去怼。然后这个时候让别人取走了,但是这里面是不是没有,然后过去一天了,别人怎么知道你曾经发了啥,是不是还有一个对系统造成进来的数据的环节,所以在这的时候你的客户端控制一个什么事情,那么这时候你要么就是,我客户端代码单调一次向它推送,然后再线性代码执行单调一次,向我socket里放,然后再系统单调一次给到我kafika,kafika这边再慢慢地向我数据库里边去累积的一些数据。好,因为你所有人聊天,对于内存速度很快的,但是这么大的并发写到数据库的时候一定会把它压踏,你可以都单调了,去完成这些事情。但是这是有人会想了,如果单调的话,我都给它发了,你挂了,后面还没执行。结果人家看到消息了,但是看不到过去的一个消息。
比如说我可以用两个redis进程,再把一个redis拆分,一个redis的进程在一台服务器只负
责发布、订阅,然后再用一个redis进程,也去订阅通道,然后这边人发了之后,给他发送
了,他这边就可以订阅,放到这边排序,然后你还可以再从另外的一个客户端,从发布、
订阅出来的消息,然后再转给kafika,再转给我们的数据库,这是不是另外一种方案?我把
它给你画一下,简单的画一下。
所以这时候其实你们来这学习,交钱之后一定要注意和同学之间互相聊天,然后增加
感情,因为别人指不定哪一句话就可以开拓你的事业,对不对?那么一个我的客户端,然
后向redis去做pub,然后发的消息,另外的一个客户端就可以从redis这儿sub走。然后另外的
一个Rides,可以从这sub走,然后放到他的zset里边。然后还可以有你的一个service,另外
的一个微服务,一个service,然后从Rides这边再去sub拿得到这个通知,然后用 service再去导到我们的kafika,然后kafika这边再由你的service去消费db service,然后db service后边接着就是我们的mySQL,关型数据库。好吧,那么注意redis其实他自己,你看刚才讲过所有的命令,他自己特别简单,但是无非就是简单的东西,在企业架构里面怎么去使用它、驾驭它, Rides自身就是内存级的了,无非就是别人对他的连接数的这么一个控制,有多个socket连接,其实成本并不是很大。好吧,因为它并不需要进行密集的CPU计算,它并不是一个计算框架,它是一个内存存储层,数据到了,然后直接向订阅的所有的socket把消息广播出去就可以
在这里插入图片描述

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐