概念
发布订阅是一种生产者/消费者模型。
由三部分组成:发布者(Publisher)、频道(Channel)、订阅者(Subscriber)。
Redis通过SUBSCRIBE,PSUBSCRIBE,UNSUBSCRIBE和PUNSUBSCRIBE等命令实现发布和订阅功能。
原理
客户端和频道的订阅关系是通过一个字典加链表的结构保存的:
在 Redis 的底层结构中,redis服务器中定义了一个pubsub_channels字典,用于保存所有频道的订阅关系,在这个字典中,key为所有频道名称,value结构是一个链表,其中存放的是所有订阅这个频道的订阅者客户端。subscribe命令的实质即为在key中添加value的订阅链。
若频道首次被订阅说明在字典中并不存在该渠道的信息,那么程序首先要新建一个对应的 key,并且要赋值一个空链表,然后将对应的客户端加入到链表中。此时链表只有一个元素。若该渠道已经被其他客户端订阅过:这个时候就直接找到key值对应的value客户端信息添加到链表的末尾即可。
使用
命令
PUBLISH命令:发送信息,返回值为接收到该消息的订阅者数量。
SUBSCRIBE命令为订阅频道
PSUBSCRIBE 命令订阅一个或多个符合给定模式的频道。
UNSUBSCRIBE命令为取消订阅频道,与订阅频道命令相同,也有对应匹配模式PUNSUBSCRIBE。
Java中使用(Jedis为例)
要使用Jedis的Publish/Subscribe功能,必须编写对JedisPubSub的自己的实现。
Jedis有两种订阅模式:subsribe(一般模式设置频道)和psubsribe(使用模式匹配来设置频道)。不管是那种模式都可以设置个数不定的频道。订阅得到信息在将会lister的onMessage(…)方法或者onPMessage(…)中进行进行处理。
缺点
redis无法对消息持久化存储,消息一旦被发送,如果没有订阅者接收,数据会丢失
消息队列提供了消息传输保障,当客户端连接超时或事物回滚的等情况发生时,消息会重新发布给订阅者,redis没有该保障,导致的结果就是在订阅者断线超时或其他异常情况时,将会丢失所有发布者发布的信息
若订阅者订阅了频道,但自己读取消息的速度很慢的话,那么不断积压的消息会使redis输出缓冲区的体积变得越来越大,这可能使得redis本身的速度变慢,甚至直接崩溃