celery delay发送redis redisson delayqueue
转载
一般实现的方法有:
- rocketMQ、rabbitMQ、pulsar等消息队列的延时投递功能;
- redisson提供的DelayQueue;
- redisson delayQueue是一种基于redis zset结构的延时队列实现,delayQueue中有一个名为 timeoutSetName 的有序集合,其中元素的score为投递时间戳。delayqueue会定时使用zrangebyscore 扫描已到投递时间的消息,然后把它们移动到就绪消息列表中。
- delayQueue在保证redis不崩溃的情况下不丢失消息
有问题的实现方法:
redis过期监听:
实现方式:
- 定时任务离线扫描并删除部分过期键;在访问建时惰性检测是否过期并删除过期键;
缺点:
- redis从未保证会在设定的过期时间立即删除并发送过期通知,过期通知晚于设定的过期时间数分钟的情况都比较常见;
- 过期通知采用发送即忘(fire and forget)策略,并不会像消息队列一样保证送达。订阅事件的客户端可能会丢失所有在断线期间所有发送给它的事件。
rabbitMq死信队列:
实现方式:
- 死信是rebbitMQ提供的一种机制;当一条消息满足一定条件会被认定为死信,死信会被投入到死信队列中。死信队列设计的目的是为了存储未被正常消费的消息,便于排除和重新投递
- 满足条件以下任一条件成为死信:
- 消息被否定确认(如clannel.basicNack),并且此时requeue属性被设置为false;
- 消息在队列的存活时间超过设置的TTL时间;
- 消息队列的消息数量已经超过最大队列长度;
- 在rabbitMq中创建死信队列的流程
- 创建一个交换机作为死信交换机;
- 在业务队列中配置x-dead-letter-exchange 和 x-dade-letter-routing-key 将第一步的死信交换机设为业务队列的交换机;
- 在死信交换机上创建队列,并监听此队列;
缺点:
- 死信队列同样不保证投递时间的即时性。
- 在第一条消息成为死信后,后面的消息即使过期也不会投递为死信。
建议:
- rabbit公司提供了延时投递插件 rabbitMq-delayed-message-exchange
使用非持久化的时间轮
实现方式:
- 时间轮本身就是一种定时任务的数据结构。
缺点:
- 绝对大多数时间轮都是纯内存,没有持久化的,运行时间轮的进程崩溃后,该时间轮内所有的任务都会灰飞烟灭。
本文章为转载内容,我们尊重原作者对文章享有的著作权。如有内容错误或侵权问题,欢迎原作者联系我们进行内容更正或删除文章。