延时任务队列-单机支持每秒10万延时消息高效触发(可部署多台提供更高并发)

本文方案是看了58的一位架构师的分享,但并没有实现细节。本文是对方案的深入研究及代码实现


业务场景


1.下单之后如果三十分钟之内或12小时没有付款就自动取消订单


2.下单成功后60s之后给用户发送短信通知


3.用户希望通过手机远程遥控家里的智能设备在指定的时间进行工作。这时候就可以将用户指令发送到延时队列,当指令设定的时间到了再将指令推送到只能设备。


4. 七天自动收货


5.一定时间后自动评价


6.业务执行失败之后隔10分钟重试一次


…….



吐舌头本质都是过一段时间后才执行任务



下单成功后60s之后给用户发送短信通知为例。


方案一: 定时扫描表



实现:启动一个定时任务,每分钟查一次数据库表,把下单成功超过60秒并且没有发过短信通知的的取出来,然后去处理。


缺点:
1.如果数据量很大,查表轮询效率就低。
2.每分钟轮询一次增加了数据库压力。
3.如果是增大轮询时间间隔,那么时效性(准确性)又降低了



方案二: redis


实现:通过zset机构模拟,定时器去读zset数据去处理。


不足:

1.数据量大,一zset性能有问题。 当然可以多定义几个zset,再数据量大的时候分散到不同zset里面,但存和定时器去读的复杂性增加了。
2.消息处理失败是不能被恢复。也有考虑过将分为TODO和Doing两条队列。但是由于Redis的事务特性,并不能做到完全可靠;并且检查Doing超时的逻辑也略复杂
并不是成熟方案,需要自己去实现。


方案三: JAVA DelayQueue

实现:DelayQueue本身就是延迟队列


不足:

1.通过先将消息排序再定时触发的方式来实现延迟消息。所以大量消息时,性能不能保证
2.想提供一定可靠性(如数据持久性),扩展性不方便
3.分布式需要额外实现


方案四: MQ


实现:老版本的MQ大多没有延时队列的实现。
       不过现在新版本慢慢有了延时投递的功能。
如:ActiveMQ 可以延时投递,但有人测试在往队列中投递大量(10w+)定时消息之后,ActiveMQ的性能将会变得接近不可用,大量的消息挤压得不到投递,可多机。
      RocketMQ 支持定时消息,但是不支持任意时间精度,支持特定的level,例如定时5s,10s,1m等。
     RabbitMQ 通过他的一些特性也可以模拟出延迟队列的功能,或者有一些第三方插件
 
完善的MQ系统可实现一个高可靠的分布式延迟消息队列。仍在发展中,但还没有完全比较专用的延迟消息功能






方案五: 自己实现延时MQ
有能力可以做,mq实现起来还是耗费资源的




方案六: 自己实现延时队列


我们自己实现轻量级的延时队列。


初级版本目标:
       网络或down机允许消息丢失。即业务完整性不保证
       支持高并发
       不提供客户端

       只做一个内嵌的jar,不单独做一个成品应用服务

源码:https://gitee.com/itman666/wheel-timer-queue

详细介绍请看wiki: https://gitee.com/itman666/wheel-timer-queue/wikis/Home 

猜你喜欢

转载自blog.csdn.net/it_man/article/details/78402837