delayQueue实现

需求背景
  • 用户下订单成功之后隔20分钟给用户发送上门服务通知短信
  • 订单完成一个小时之后通知用户对上门服务进行评价
  • 业务执行失败之后隔10分钟重试一次

    类似的场景比较多 简单的处理方式就是使用定时任务 假如数据比较多的时候 有的数据可能延迟比较严重,而且越来越多的定时业务导致任务调度很繁琐不好管理。

序号

方案

实现原理

优点

缺点

1

java DelayQueue

wait-notify机制不引入其他服务依赖,wait-notify机制,不做polling,不会浪费cpu。数据保存在JVM内存中,当应用重启会造成数据丢失,或者数据量大时造成DelayQueue过大。
2

RabbitMQ 死信队列

利用ttl 以及DLE (Dead Letter Exchanges)可以模拟出延迟队列

开源,现成的稳定的实现方案每个延迟时间需要单独一个队列(5分钟延时是一个,10分钟延迟是另外一个)。除此以外,使用较复杂,对开发者有一定的要求。
3

redis zset

使用ZSET做优先队列,按照Score维持优先级

设定轮询,每分钟轮询一次zset,找出score小于当前秒数的数据,进行处理,然后将key在zset内删除

比较简单,支持持久化比较简陋的延时队列,有意外报错的话,大不了就多轮询几次。或者等人发现了再解决,也没有ack机制,所以也是挺不靠谱的,使用在不太重要的地方还行
4

自研DelayQueue

执行过程:

参数说明:

  • Topic:一组相同类型Job的集合(队列)。供消费者来订阅。
  • Id:Job的唯一标识。用来检索和删除指定的Job信息。
  • Delay:Job需要延迟的时间。单位:秒。(服务端会将其转换为绝对时间)
  • Body:Job的内容,供消费者做具体的业务处理,以json格式存储。
  • callBack:回调接口地址。使用http协议,该地址是一个url。

存储结构

名称

redis类型

保存数据格式

delayJob状态

FailedDelayJob状态

DelayQzsetjob--->scorepublishedN/A
ReadyQhash tablejobId--->jobreadyready
FailedDelayQzsetjob--->scoreN/Apublished

状态转换说明:

1. 客户端publish一个job,首先会被保存到delayQ中,此时状态为published(DelayJob)

2. 超时后,会从delayQ中取出,放入ReadyQ中,状态为Ready(DelayJob)

3 回调成功,则删除readyQ状态是deleted(DelayJob);

4 回调失败,DelayedJob 变为FailedDelayJob(transfer)删除readyQ信息状态为published(FailedDelayJob)

5.FailedDelayJob超时,会从FailedDelayQ删除,放入ReadyQ,状态为Ready(FailedDelayJob);

6.回调成功,则删除readyQ,状态是deleted(FailedDelayJob);

7.回调失败,小于重试次数,则再次transfer,删除readyQ信息,状态为published(FailedDelayJob);

8.回调失败,超过重试次数,则归档,发提示短信,同时删除readyQ&数据字典信息,deleted(FailedDelayJob)。

DelayJob和FailedDelayJob转换:

 

  • 33
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值