延迟队列技术方案

什么场景需要使用延迟队列

1、订单成功后,在30分钟内没有支付,自动取消订单
2、外卖平台发送订餐通知,下单成功后60s给用户推送短信。
3、如果订单一直处于某一个未完结状态时,及时处理关单,并退还库存
4、淘宝新建商户一个月内还没上传商品信息,将冻结商铺等

我们的需求

  • 最长每三天执行一次,最短的1s(iap支付,续费重试)
    (https://yuque.antfin.com/tp_team/ohzygl/fx4caw)
  • 高可用、不允许数据丢失
  • 对实时性要求不高,允许延迟误差
  • 允许重复消费(服务方做幂等)
  • 需要监控(队列堆积)
  • 可查询延迟队列单key的消费情况

现有方案

  • JDK自带的DelayQueue(不适合我们目前的场景)

  • 定时任务 + DB + Redis

  • Redis sortedSet

  • Reids过期回掉(不是很靠谱)

  • RocketMQ (1s/5s/10s/30s/1m/2m/3m/4m/5m/6m/7m/8m/9m/10m/20m/30m/1h/2h)
    解决定时的方案: 根据level,消费时重新投递。
    存在在db,定时消费。

  • RabbitMQ(TTL & DLX)

  • Netty 时间轮

目前开源的延迟消息,也就pulsar比较可靠,其次是rocketmq,但rocket只支持18个等级的固定刻度,pulsar也是近几天内的任意时间,长时间不行。其他的,rabbit不适合大量堆积,redis key多的时候会严重滞后(惰性删除),而且没有ack。sorted set,在field超过一定量时预计5000左右会产生性能问题,需要做二次分片。jdk的delayqueue,性能就不提了,只能做短时、量少的延迟消息,而且还没有ack,可能存在丢失,如果要写入数据库,也很麻烦。内存时间轮性能好点,但也没法ack,而且消费阻塞会引起问题(单线程)
目前最佳实践就是组合以上的几种,定时任务+pulsar/rocket本身时间轮等,多重组合,可以实现海量,超长时间的延迟消息(不修改几种组件源码的情况下)

参考链接:
https://www.cnblogs.com/rickiyang/p/12237612.html

https://juejin.cn/post/6844904150703013901

https://www.gameres.com/875153.html

饿了么交易域的延迟队列方案分析

https://www.cnblogs.com/hzmark/p/mq-delay-msg.html

你可能感兴趣的:(延迟队列技术方案)