广告
返回顶部
首页 > 资讯 > 数据库 >Redis中如何实现消息队列和延时消息队列
  • 926
分享到

Redis中如何实现消息队列和延时消息队列

2024-04-02 19:04:59 926人浏览 八月长安
摘要

这篇文章将为大家详细讲解有关Redis中如何实现消息队列和延时消息队列,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。list的几个命令lpush (left push)由

这篇文章将为大家详细讲解有关Redis中如何实现消息队列和延时消息队列,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

list的几个命令

lpush (left push)

由队列的左边存放进去

rpush (right push)

由队列的右边存放进去

lpop  (left pop)

由队列的左边取出来

rpop (right pop)

由队列的右边取出来

以上的四个命令,可以让 list 帮我们实现队列 或者 栈,队列的特性是先进先出,栈的特性是先进后出,

所以队列的实现可以使用 lpush + rpop 或者 rpush + lpop,

栈的实现则是lpush + lpop 或者 rpush + rpop。

Redis中如何实现消息队列和延时消息队列

使用命令演示队列

生产者发布消息

首先我们使用 rpush 对一个叫做notify-queue的队列,增加五个元素,即 1 2 3 4 5,也就是作为生产者发布消息啦

Redis中如何实现消息队列和延时消息队列

消费者消费消息

既然生产者使用的是rpush,那么消费者就要用lpop,可以看下下图,我们不停对notify-queue进行消息消费,并且是按照顺序的,从1一直到5,按顺序读出,最终队列中没有消息了,弹出的则一直是空

Redis中如何实现消息队列和延时消息队列

空轮询问题

在上面使用lpop消费消息时,可以看到,消息消费完后,我们每次再去pop时,读到的都是一个空的信息,

上面是手动执行命令,但是如果是写好的代码程序不停的去pop数据(拉取数据)的话,会造成空轮询(无用的读取),

既拉高了客户端的CPU消耗,又拉高了redis的QPS,并且还是无用操作,这些无用操作可能会造成其他客户端对redis的访问变得响应缓慢。

解决方案A (休眠)

既然空轮询会让客户端和redis的资源消耗都会变得较高,那么我们可以让客户端在收到空数据的时候,进行1s的休眠,1s后再进行数据拉取,这样可以降低消耗

Thread.sleep(1000)

这个方案也是存在瑕疵的,即消息消费延迟性增大了,如果只有一个消费者的话,延迟就是1s,即空轮询后,正好休眠了,但是这时候刚好有消息过来了,还是要等到1s醒来后才能消费,

如果有多个消费者的话,由于每个消费者的睡眠时间是岔开的,会降低一些延迟性,但是有没有办法更好的方法,可以做到几乎 0 延迟?

解决方案B (阻塞读)

redis中关于队列取数据其实还有两个命令,即阻塞读取,

blpop (blocking left pop)

brpop (blocking right pop)

阻塞读在队列没有数据的时候,会进入休眠状态,一旦有消息来了以后,则立刻做出反应,读取数据,因此使用 blpop/brpop 替换 lpop/rpop 则可以解决消息延迟性的问题,

继续入队3个属性,6、7、8

Redis中如何实现消息队列和延时消息队列

使用 blpop 进行队列的读取,最后一个参数是阻塞读的等待时间,如果超过这个时间还没有消息,将会返回nil,此时可以继续重复blpop操作,

Redis中如何实现消息队列和延时消息队列

阻塞读的空闲连接自动断开问题

客户端使用阻塞读时,如果阻塞的时间过长,服务一般会当成空闲连接,从而对其进行主动断开,减少无用的连接占用资源,这个时候客户端会抛出异常,

所以请注意,在客户端使用阻塞读的时候,要进行异常的捕获,从而做出相应的处理,例如重试。

java客户端实现消息队列

思路和上述一样,只是由命令行客户端redis-cli变成了java语言,一个线程或多个线程进行 rpush 的发布,

另外一个或多个线程进行 blpop 消费,完成的代码在:https://GitHub.com/qiaomengnan16/redis-demo/tree/main/redis-queue

发布者

Redis中如何实现消息队列和延时消息队列

订阅者

Redis中如何实现消息队列和延时消息队列

延时队列的实现思路

延时队列指的是,消息发送的一段时间后,再由消费者进行消费,而不是发送过去后,消费者就能立即读取到,

zset的可以帮我们做到这个事情,首先zset可以通过score进行排序,score可以存一个时间戳,所以我们每次发布消息的时候,用当前时间戳加上延时的时间戳,

随后消费者取消息的时候,通过截取zset的数据,取到已经满足当前时间的消息(即取score小于等于当前时间戳的数据,score小于等于当前时间戳代表消息已经到时间了,如果大于的话,说明还得等一会才能消费)。

关键命令 zadd (发布者),zrangebyscore(订阅者),zrem (订阅者消费完数据后删除)

命令实现

我们使用zadd添加了4个数据,分别是1、2、3秒(伪说法,这里其实只是个score)后才能消费的数据,还有一个10秒后才能消费的kafka

Redis中如何实现消息队列和延时消息队列

假如现在已经到了第三秒,我们取zset中大于等于1秒的和小于等于3秒的数据,因为这个区间的数据正好是我们可以消费的,可以看到,我们取出了符合条件的3条数据,

Redis中如何实现消息队列和延时消息队列

如果每次只能消费一个数据的话,可以加一个limit限制条件,可以看下图取出了第一个可以消费的数据,redis

Redis中如何实现消息队列和延时消息队列

同时注意,和list的lpop/和blpop不同(它们弹出即自动删除原始队列里的该数据),

虽然获取到了数据,但是如果不使用zrem进行删除的话,这条数据还会被其他人读到,因为他还一直存在zset中,

不过zrem可能会发生已经被别人抢先一步删除(消费)的情况,所以代码中还需要根据zrem的返回值是否大于0判断,本次消息我们是否抢占成功,成功后再进行正确消费。

代码实现

发布者

Redis中如何实现消息队列和延时消息队列

订阅者

Redis中如何实现消息队列和延时消息队列

测试延迟效果

Redis中如何实现消息队列和延时消息队列

完整代码地址:Https://github.com/qiaomengnan16/redis-demo/tree/main/redis-delayed-queue

优化, 使用lua实现

上面实现的延迟队列中,有一个问题,就是使用zrem判断是否抢到这个数据时,很有可能没有抢到,这样继续进行读取,可能几轮都抢不到,资源白白浪费了,所以可以通过lua脚本,来进行优化

让zrangebyscore 和 zrem成为一个原子化操作,这就可以避免多线程争抢,抢不到的资源浪费了。

Redis中如何实现消息队列和延时消息队列

Redis中如何实现消息队列和延时消息队列

关于“Redis中如何实现消息队列和延时消息队列”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

您可能感兴趣的文档:

--结束END--

本文标题: Redis中如何实现消息队列和延时消息队列

本文链接: https://www.lsjlt.com/news/69707.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Redis中如何实现消息队列和延时消息队列
    这篇文章将为大家详细讲解有关Redis中如何实现消息队列和延时消息队列,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。list的几个命令lpush (left push)由...
    99+
    2022-10-19
  • redis消息队列如何延时
    redis消息队列延时的示例:延时队列可通过zset来实现,消息的处理时间作为score,最后通过多线程轮询获取到期的score任务即可,代码:public class DelayQueue {static class TaskItem {...
    99+
    2022-10-17
  • Java实现Redis延时消息队列
    目录什么是延时任务 延时任务的特点 实现思路: 代码实现 1.消息模型2.RedisMq 消息队列实现类3.消息生产者 4.消息消费者 5. 消息执接口 6. 任务类型的实现类:可以...
    99+
    2022-11-12
  • redis中的消息队列
    这期内容当中的小编将会给大家带来有关redis中的消息队列介绍,以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。一、认识消息队列1.1 消息队列概念“消息”是在两台计算机间传送的数据单位。...
    99+
    2022-11-30
    redis 消息队列 edi
  • redis怎么实现消息队列
    Redis可以通过以下几种方式实现消息队列:1. List数据结构:使用Redis的List数据结构实现简单的消息队列。生产者将消息...
    99+
    2023-09-14
    redis
  • Redis如何实现消息队列功能
    Redis如何实现消息队列功能随着互联网的发展,消息队列在分布式系统中变得越来越重要。消息队列允许不同的应用程序之间通过异步通信来传递和处理消息,提高了系统的可伸缩性和可靠性。Redis作为一款快速、可靠、灵活的内存数据库,也可以用来实现消...
    99+
    2023-11-07
    redis 实现 消息队列
  • 如何使用redis实现消息队列
    使用redis实现消息队列的示例:redis的pubsub功能实现发布订阅模式,代码:import redisclass Task(object):def __init__(self):self.rcon = redis.StrictRed...
    99+
    2022-10-24
  • golang消息队列实现
    Golang是一种开源的编程语言,它适用于创建高性能的网络应用程序和消息队列等分布式系统。在这篇文章中,我们将探讨如何使用Golang来实现一个消息队列。什么是消息队列?在分布式系统中,应用程序通常需要在不同的节点之间共享数据。消息队列是用...
    99+
    2023-05-15
  • 如何监听redis消息队列
    监听redis消息队列的示例:springBoot实现redis发布式监听消息队列,定时器监听不同功能的消息,代码:import org.springframework.context.annotation.Bean;import org....
    99+
    2022-10-19
  • redis实现消息队列的方法
    这期内容当中的小编将会给大家带来有关redis实现消息队列的方法,以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。消息队列,Message Queue,常用于解决并发系统中的资源一致性问题...
    99+
    2022-10-18
  • Redis中如何使用消息队列
    这篇文章主要介绍了Redis中如何使用消息队列,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。说到消息队列中间件,我们都会想到RabbitMQ...
    99+
    2022-10-19
  • redis stream 实现消息队列的实践
    目录Redis 实现消息对列4中方法发布订阅list 队列zset 队列Stream 队列基本命令xadd 生产消息读取消息xgroup 消费者组xreadgroup 消费消息Pending 等待列表消息确认消息转移信息...
    99+
    2022-08-10
    redisstream消息队列 redis消息队列
  • 如何利用redis做消息队列
    利用redis做消息队列的示例:生产者模拟程序,代码:package scheduleTest; import java.util.Random; import java.util.UUID; import redis.clients.je...
    99+
    2022-10-14
  • java如何监听redis消息队列
    java监听redis消息队列的方法:可以使用springBoot实现redis发布式监听消息队列,定时器监听不同功能的消息。java监听redis消息队列的示例:springBoot实现redis发布式监听消息队列,定时器监听不同功能的消...
    99+
    2022-10-04
  • SpringBoot2实现MessageQueue消息队列
    目录什么是消息队列一、异步与同步1.1 同步通讯与异步通讯1.2 同步调用的问题1.3 异步调用方案二、MQ消息队列2.1 单机部署MQ2.2 结构和概念2.3 常见的消息模型三、S...
    99+
    2023-05-17
    SpringBoot2 MessageQueue消息队列 SpringBoot MessageQueue
  • Redis消息队列怎么实现秒杀
    要实现秒杀功能,可以使用Redis的消息队列来进行异步处理。下面是一种基本的实现方法:1. 准备工作:创建一个商品库存键值对,如"s...
    99+
    2023-10-11
    Redis
  • redis中队列消息实现应用解耦
    本篇文章给大家分享的是有关redis中队列消息实现应用解耦,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。1、如果redis服务器挂掉了怎么办啊...
    99+
    2022-10-18
  • 如何利用rabbitMq的死信队列实现延时消息
    目录前言mq基本的消息模型mq死信队列的消息模型maven依赖配置普通队列和死信队列死信队列消费者发送消息测试测试成功总结前言 使用mq自带的死信去实现延时消息要注意一个坑点,就是m...
    99+
    2023-01-28
    rabbitMq死信队列 rabbitMq延时消息 rabbitMq延时队列
  • Redis在消息队列中的妙用
    Redis在消息队列中的妙用消息队列是一种常见的解耦架构,用于在应用程序之间传递异步消息。通过将消息发送到队列中,发送者可以在不等待接收者响应的情况下继续执行其他任务。而接收者可以在适当的时间从队列中获取消息并进行处理。Redis是一种常用...
    99+
    2023-11-07
    redis 消息队列 妙用
  • RabbitMQ消息队列怎么实现延迟任务
    这篇文章主要介绍“RabbitMQ消息队列怎么实现延迟任务”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“RabbitMQ消息队列怎么实现延迟任务”文章能帮助大家解决问题。一、序言延迟任务应用广泛,延...
    99+
    2023-06-29
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作