delay-queue

redis实现延迟消息队列

需求背景

最近在做一个排队取号的系统

在用户预约时间到达前XX分钟发短信通知

在用户预约时间结束时要判断用户是否去取号了,不然就记录为爽约

在用户取号后开始,等待XX分钟后要发短信提醒是否需要使用其他渠道办理

类似的场景太多,最简单的解决办法就是定时任务去扫表。这样每个业务都要维护自己的扫表逻辑,

而且随着时间的推移数据量会越来越多的,有的数据可能会延迟比较大

经过一番搜索,网上说rabbitmq可以满足延迟执行需求,但是目前系统用了其他消息中间件,所以不打算用。

基于Redis实现的延迟消息队列java版:项目github地址:delay-queue

整体结构

整个延迟队列由4个部分组成:

JobPool用来存放所有Job的元信息。利用redis 的hash结构

DelayBucket是一组以时间为维度的有序队列,用来存放所有需要延迟的Job(这里只存放Job Id)。利用redis 的 有序集合zset

Timer负责实时扫描各个Bucket,并将delay时间大于等于当前时间的Job放入到对应的Ready Queue。利用redis 的list 结构

ReadyQueue存放处于Ready状态的Job(这里只存放JobId),以供消费程序消费。

结构图

消息结构

每个Job必须包含一下几个属性:

topic:Job类型。可以理解成具体的业务名称。

id:Job的唯一标识。用来检索和删除指定的Job信息。

delayTime:jod延迟执行的时间,13位时间戳

ttr(time-to-run):Job执行超时时间。单位:秒。主要是为了消息可靠性

message:Job的内容,供消费者做具体的业务处理,以json格式存储。

举例说明一个Job的生命周期

用户预约后,同时往JobPool里put一个job。job结构为:{‘topic':'book’, ‘id':'123456’, ‘delayTime’:1517069375398 ,’ttrTime':60 , ‘message':’XXXXXXX’}

同时以jobId作为value,delayTime作为score 存到bucket 中,用jobId取模,放到10个bucket中,以提高效率

timer每时每刻都在轮询各个bucket,按照score排序去最小的一个,当delayTime < 当前时间后,,取得job id从job pool中获取元信息。

如果这时该job处于deleted状态,则pass,继续做轮询;如果job处于非deleted状态,首先再次确认元信息中delayTime是否大于等于当前时间,

如果满足则根据topic将jobId放入对应的ready queue,然后从bucket中移除,并且;如果不满足则重新计算delay时间,再次放入bucket,并将之前的job id从bucket中移除。

消费端轮询对应的topic的ready queue,获取job后做自己的业务逻辑。与此同时,服务端将已经被消费端获取的job按照其设定的TTR,重新计算执行时间,并将其放入bucket。

消费端处理完业务后向服务端响应finish,服务端根据job id删除对应的元信息。如果消费端在ttr时间内没有响应,则ttr时间后会再收到该消息

后续扩展

加上超时重发次数

实现思路

任务job内容包含Array{0,0,2m,10m,10m,1h,2h,6h,15h}和通知到第几次N(这里N=1, 即第1次).

消费者从队列中取出任务, 根据N取得对应的时间间隔为0, 立即发送通知.

第1次通知失败, N += 1 => 2

从Array中取得间隔时间为2m, 添加一个延迟时间为2m的任务到延迟队列, 任务内容仍包含Array和N

第2次通知失败, N += 1 => 3, 取出对应的间隔时间10m, 添加一个任务到延迟队列, 同上

......

第7次通知失败, N += 1 => 8, 取出对应的间隔时间15h, 添加一个任务到延迟队列, 同上

第8次通知失败, N += 1 => 9, 取不到间隔时间, 结束通知

引用说明

参考有赞延迟队列思路设计实现

java redis延迟队列_基于redis实现的延迟消息队列相关推荐

  1. java redis id生成器_基于redis的分布式ID生成器

    项目地址 基于redis的分布式ID生成器. 准备 首先,要知道redis的EVAL,EVALSHA命令: 原理 利用redis的lua脚本执行功能,在每个节点上通过lua脚本生成唯一ID. 生成的I ...

  2. java分布式调度框架_基于Redis的分布式Java任务执行和调度框架

    Redisson是使用Redis实现分布式任务执行和调度的Java开源项目,它是通过标准JDK的ExecutorService和ScheduledExecutorService API实现的,被提交的 ...

  3. python分布式任务调度_Python使用Celery分布式异步队列/任务调度(基于Redis) - pytorch中文网...

    今天使用爬虫有些耗时较长,需要使用任务调度,Celery是Python开发的分布式任务调度模块,Celery本身不含消息服务,它使用第三方消息服务来传递任务,目前,Celery支持的消息服务有Rabb ...

  4. 有什么办法动态更改yml的值吗_基于Redis实现Spring Cloud Gateway的动态管理

    转载本文需注明出处:微信公众号EAWorld,违者必究. 引言: Spring Cloud Gateway是当前使用非常广泛的一种API网关.它本身能力并不能完全满足企业对网关的期望,人们希望它可以提 ...

  5. redistemplate分布式锁实现_基于 Redis SETNX 实现分布式锁

    环境与配置 Redis 任意版本即可 SpringBoot 任意版本即可,但是需要依赖 spring-boot-starter-data-redis <dependency><gro ...

  6. Redis 笔记(04)— list类型(作为消息队列使用、在列表头部添加元素、尾部删除元素、查看列表长度、遍历指定列表区间元素、获取指定区间列表元素、阻塞式获取列表元素)

    Redis 的列表是链表而不是数组.这意味着 list 的插入和删除操作非常快,时间复杂度为 O(1),但是索引定位很慢,时间复杂度为 O(n). 当列表弹出了最后一个元素之后,该数据结构自动被删除, ...

  7. php redis消息队列用哪种好,phpredis提高消息队列的实时性方法(推荐)

    搜索热词 数据库存贮都用list形式 要存2个队列 1个用作消息队列保存到数据 还有个 就是用来实时读取数据在redis $redis->lpush($queenkey,json_encode( ...

  8. java项目----教务管理系统_基于Java的教务管理系统

    java项目----教务管理系统_基于Java的教务管理系统 2022-04-22 18:18·java基础 最近为客户开发了一套学校用教务管理系统,主要实现学生.课程.老师.选课等相关的信息化管理功 ...

  9. java队列处理高并发_Java高并发--消息队列

    Java高并发--消息队列 举个例子:在购物商城下单后,希望购买者能收到短信或者邮件通知.有一种做法时在下单逻辑执行后调用短信发送的API,如果此时服务器响应较慢.短信客户端出现问题等诸多原因购买者不 ...

最新文章

  1. 0x02 mysql 表格相关操作
  2. pytorch读取文本训练
  3. BZOJ4066:简单题(K-D Tree)
  4. 【CodeForces - 558C】Amr and Chemistry(位运算,bfs,计数,思维,tricks)
  5. idea报错Module Project1 must not contain source root ...\Project1\src. The root already belongs to m
  6. 计算机网络(第七版)谢希仁编著 前五章课后答案计算题详解
  7. jquery实现简单的滑动解锁
  8. 【网络】TCP报文头部
  9. 网易云接口加直链下载vip歌曲
  10. java-net-php-python-java《Linux基础及技术》课程网站演示录像修改计算机毕业设计程序
  11. Python学习实验报告(1)
  12. maven自定骨架创建流程
  13. 关于 360 度评估
  14. python批量加微信好友_python如何自动批量添加微信好友并修改备注
  15. 百度网盘怎么批量改名(包含子文件夹)
  16. 用JS实现贪吃蛇小游戏
  17. 时序数据库为万物互联打下坚实的基石
  18. 值得学习的开源web项目
  19. Oracle Primavera P6 文档管理与文件查看(Autovue及Outsidein)
  20. 前端学习日记2-html表单元素

热门文章

  1. Java动态代理技术-我的浅显认识
  2. 餐饮行业选址如何用大数据软件了解相关要素
  3. HIHO#1245 : 王胖浩与三角形
  4. Premiere导出视频音画不同步的解决方案
  5. 用latex排版LNCS模板的论文
  6. 正点原子OLED显示实验
  7. l7sa008b故障代码_麦克维尔空调故障代码速查
  8. java获取每周的周一到周日时间节点
  9. vs.net发送邮件(2.0)
  10. Java 结构化数据处理开源库SPL,再也不用苦哈哈写SQL了