redis如何实现队列的阻塞、延时、发布和订阅


这篇文章主要介绍了redis如何实现队列的阻塞、延时、发布和订阅的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇redis如何实现队列的阻塞、延时、发布和订阅文章都会有所收获,下面我们一起来看看吧。Redis不仅可作为缓存服务器,还可以用作消息队列。它的列表类型天生支持用作消息队列。如下图所示:
由于Redis的列表是使用双向链表实现的,保存了头节点和尾节点,所以在列表的头部和尾部两边插入或获取元素都是非常快的,时间复杂度为O(1)。可以直接使用Redis的list数据类型实现消息队列,只需简单的两个指令lpush和r免费云主机域名pop或者rpush和lpop。lpush+rpop:左进右出的队列rpush+lpop:左出右进的队列下面使用redis的命令来模拟普通队列。
使用lpush命令生产消息:使用rpop命令消费消息:下面使用Java代码来实现普通队列。生产者SingleProducer消费者SingleConsumer:上面的代码已经基本实现了普通队列的生产与消费,但是上述的例子中消息的消费者存在两个问题:消费者需要不停的调用rpop方法查看redis的list中是否有待处理的数据(消息)。每调用一次都会发起一次连接,有可能list中没有数据,造成大量的空轮询,导致造成不必要的浪费。也许你可以使用Thread.sleep()等方法让消费者线程隔一段时间再消费,如果睡眠时间过长,这样不能处理一些时效性要求高的消息,睡眠时间过短,也会在连接上造成比较大的开销。如果生产者速度大于消费者消费速度,消息队列长度会一直增大,时间久了会占用大量内存空间。消费者可以使用brpop指令从redis的list中获取数据,这个指令只有在有元素时才返回,没有则会阻塞直到超时返回null,于是消费端就不需要休眠后获取数据了,这样就相当于实现了一个阻塞队列,使用redis的brpop命令来模拟阻塞队列。可以看到命令行阻塞在了brpop这里了,30s后没数据就返回。Java代码实现如下:生产者与普通队列的生产者一致。消费者BlockConsumer:缺点:无法实现一次生产多次消费。Redis除了对消息队列提供支持外,还提供了一组命令用于支持发布/订阅模式。利用Redis的pub/sub模式可以实现一次生产多次消费的队列。发布:PUBLISH指令可用于发布一条消息,格式:返回值表示订阅了该消息的数量。订阅:SUBSCRIBE指令用于接收一条消息,格式:使用SUBSCRIBE指令后进入了订阅模式,但是不会接收到订阅之前publish发送的消息,这是因为只有在消息发出去前订阅才会接收到。在这个模式下其他指令,只能看到回复。回复分为三种类型:如果为subscribe,第二个值表示订阅的频道,第三个值表示是已订阅的频道的数量如果为message(消息),第二个值为产生该消息的频道,第三个值为消息如果为unsubscribe,第二个值表示取消订阅的频道,第三个值表示当前客户端的订阅数量。下面使用redis的命令来模拟发布订阅模式。生产者:消费者:Java代码实现如下:生产者PubsubProducer:消费者PubsubConsumer:消费者可以启动多个,每个消费者都能收到所有的消息。可以使用指令UNSUBSCRIBE退订,如果不加参数,则会退订所有由SUBSCRIBE指令订阅的频道。Redis还支持基于通配符的消息订阅,使用指令PSUBSCRIBE (pattern subscribe),例如:用PSUBSCRIBE指令订阅的频道也要使用指令PUNSUBSCRIBE指令退订,该指令无法退订SUBSCRIBE订阅的频道,同理UNSUBSCRIBE也不能退订PSUBSCRIBE指令订阅的频道。同时PUNSUBSCRIBE指令通配符不会展开。例如:PUNSUBSCRIBE *不会匹配到channel.*,所以要取消订阅channel.*就要这样写PUBSUBSCRIBE channel.*。Redis的pub/sub也有其缺点,那就是如果消费者下线,生产者的消息会丢失。Redis中有个数据类型叫Zset,其本质就是在数据类型Set的基础上加了个排序的功能而已,除了保存原始的数据value之外,还提供另一个属性score,这一属性在添加修改元素时候可以进行指定,每次指定后,Zset会自动重新按新的score值进行排序。如果score字段设置为消息的优先级,优先级最高的消息排在第一位,这样就能实现一个优先级队列。如果score字段代表的是消息想要执行时间的时间戳,将它插入Zset集合中,便会按照时间戳大小进行排序,也就是对执行时间先后进行排序,集合中最先要执行的消息就会排在第一位,这样的话,只需要起一个死循环线程不断获取集合中的第一个元素,如果当前时间戳大于等于该元素的score就将它取出来进行消费删除,就可以达到延时执行的目的,注意不需要遍历整个Zset集合,以免造成性能浪费。下面使用redis的zset来模拟延时队列。生产者:消费者:Java代码如下:生产者DelayProducer:消费者:延时队列可用于订单超时失效的场景二级缓存(local+redis)中,当有缓存需要更新时,可以使用发布订阅模式通知其他服务器使得本地缓存失效。关于“redis如何实现队列的阻塞、延时、发布和订阅”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“redis如何实现队列的阻塞、延时、发布和订阅”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注百云行业资讯频道。

相关推荐: 数据库中plan_hash_value有什么用

这篇文章给大家分享的是有关数据库中plan_hash_value有什么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。 plan_hash_value判断sql的访问路径是否改变的主要方法是:v$sql.plan_hash_valu…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

(0)
打赏 微信扫一扫 微信扫一扫
上一篇 01/23 22:12
下一篇 01/23 22:13