1.Redis的两种发布/订阅模式
2.Redis 协议 事务 发布订阅 异步连接
Redis的两种发布/订阅模式
Redis 通过 PUBLISH、SUBSCRIBE 等命令实现订阅与发布模式,提供两种信息机制:订阅/发布到频道与订阅/发布到模式。首先讨论订阅/发布到频道的实现,然后探讨订阅/发布到模式的实现。
频道订阅与信息发送使用 SUBSCRIBE 命令,vb控制源码允许客户端订阅任意数量的频道。每当新信息发送到被订阅的频道时,信息会发送给所有订阅指定频道的客户端。以频道 channel1 为例,订阅该频道的三个客户端—client2、client5、client1 会接收到信息。
订阅频道时,Redis服务器维护一个表示服务器状态的 redis.h/redisServer 结构,其中 pubsub_channels 字典保存订阅频道信息。键为频道,值为链表,社群讲课大师源码链表存储所有订阅该频道的客户端。客户端执行 SUBSCRIBE 命令时,将客户端与要订阅的频道关联到字典中。
发送信息到频道时,程序根据 channel 定位到字典的键,然后将信息发送给字典值链表中的所有客户端。在示例中,客户端执行 PUBLISH channel1 "hello moto" 命令,client2、client5、client1 将接收到 "hello moto" 信息。
退订频道通过 UNSUBSCRIBE 命令实现,执行订阅的反操作,从 pubsub_channels 字典的给定频道中删除客户端信息,被退订频道的信息不再发送给该客户端。
模式订阅与信息发送时,使用 PUBLISH 命令发送信息到频道,投机fh指标源码不仅订阅该频道的客户端会收到信息,如果模式与频道匹配,订阅该模式的客户端同样会收到信息。模式订阅与频道订阅结合,客户端可以接收多种匹配的频道信息。
模式订阅通过 redisServer.pubsub_patterns 链表实现,链表保存所有与模式相关的信息。每当执行 PSUBSCRIBE 命令订阅模式时,程序创建包含客户端信息和被订阅模式的 pubsubPattern 结构,并添加到链表中。客户端订阅 tweet.shop.* 模式后,可以接收匹配的频道信息。
发送信息到模式时,除了将信息发送给订阅 channel 的客户端,还会将 channel 和 pubsub_patterns 中的模式进行对比,如果 channel 和模式匹配,同样将信息发送给订阅该模式的源码供应链客户端。
退订模式使用 PUNSUBSCRIBE 命令,执行订阅模式的反操作,删除与被退订模式相关联的 pubsubPattern 结构,客户端不再接收与模式匹配的频道信息。
总结,Redis 的订阅与发布模式通过频道与模式实现,提供高效的信息分发机制,支持多种客户端订阅与接收信息。
Redis 协议 事务 发布订阅 异步连接
redis网络协议
1.1、redis网络
微观上:reactor
宏观上:可以忽略其他流程,只关注数据包处理流程。当管道(连接)构成一个完整的包,处理对应的事件。
1.2、redis协议
redis协议设计
redis采用RESP序列化协议,协议的不同部分使用以CRLF(\r\n)结束。
RESP支持的扶摇直上源码数据类型,通过第一个字符判断数据类型
RESP在redis请求-响应协议中的作用方式
来看下面例子
在redis-cli,发送一条命令set key value,对应的报文为:
执行成功OK,回应的报文为:
若执行失败,回应的报文为
2、redis pipeline
redis pipeline是redis客户端提供的机制,与redis本身无关,是为了节约网络传输时间而设计的。具体来说,客户端一次性发送多个请求,redis服务器按序依次回复,与http 1.1类似。
3、redis事务
事务:用户定义一系列数据库操作,这些操作视为一个完整的逻辑处理工作单元,要么全部执行,要么全部不执行,是不可分割的工作单元。
探讨事务的前提:在并发连接的情况下,不同连接异步执行命令造成的不可预期的冲突。
3.1、事务的特征
3.2、事务命令
redis客户端以MULTI开启一个事务,发送多个命令到服务端的队列,直到发送EXEC命令后redis服务端才会执行队列中的命令,将队列作为一个整体来执行。
实际工作中不会使用,这是因为事务命令是由乐观锁实现的,失败需要重试,会增加业务逻辑的复杂程度。
3.3、* lua脚本
redis内置lua解释器来执行lua脚本,通过lua脚本实现原子性。
面试点:lua脚本满足原子性和隔离性,不满足一致性和持久性。
3.3.1、命令
3.3.2、应用
例:执行加倍操作
4、redia发布订阅
为了支持消息的多播机制,redis引入了发布订阅模块,是一种分布式消息队列机制。订阅者通过特定的频道来接收发送者发送至该频道的消息。该机制并不保证消息一定到达,可以采用stream方式确保可达。
存在的问题有:发送者发送一条消息,若没有订阅者,则消息直接丢弃。若发送期间,一个订阅者断开连接,那么在断开连接期间消息对于该订阅者来说彻底丢失了。此外,redis停机重启,pubsub的消息是不会持久化的,所有的消息被直接丢弃。
4.1、命令
4.2、应用
发布订阅功能一般要重新开启一个连接,这是因为命令连接严格遵循请求回应模式,pubsub能收到redis主动推送的内容。所以实际项目中如果支持pubsub的话,需要另开一条连接用于处理发布订阅。
5、redis异步连接
hiredis是一个redis的C客户端库函数,服务端可以使用它来访问redis服务器。
5.1、同步连接
同步连接采用阻塞io来实现,但是会阻塞当前线程,直至redis返回结果。
参考文档:hiredis的使用
例如:访问redis,并对counter实现自增次,统计用时。
5.2、异步连接
异步连接采用非阻塞io实现,不会阻塞当前线程。缺点是代码书写异步,业务逻辑割裂,可以通过携程解决。在有大量并发请求的情况,配合redis 6.0以后的io多线程,异步连接池,能更好解决应用层的数据访问性能
5.2.1、redis驱动
redis驱动:服务端使用异步连接,需要自己来实现redis驱动,也就是说需要把redis连接融合自己项目中的reactor进行管理。
接着还需要设计redis适配器,其主要功能有:
综上所述,hiredis的封装规则有:
5.2.2、范例
这里对4.1的例子使用异步的方法来实现。
第1步,实现redis驱动
第2步,实现redis适配器,主要是构建redis事件对象和适配hiredis的事件控制接口。
接下来,实现主体代码,实现功能