基于redis实现可靠的延时队列

基于redis实现可靠的延时队列

源码地址,欢迎star

调度流程图调度流程图

整体实现要点

  1. seata保证业务和消息的一致性

    • 后续可以将消息和业务放到微服务本地库,使用本地事务即可保证一致性
  2. load模块

    • 基于定时任务加载消息库消息到内存

    • 应用启动时基于检查点进行消息加载

    • checkpoint机制保证获取较新故障恢复点,结合消息状态减少重复投递

    • 定时预加载与及时入库结合,保证消息投递及时性和中转效率

  3. port模块

    主要负责中转调度

    • 接受业务及时投递和定时任务投递,转储到实际的延时队列中
      • 依赖外部延时队列实现,如java DelayQueue,redission RDelayedQueue
    • 阻塞获取延时队列到期元素,投递到mq中
      • 结合不同MQ平台实现100%投递。
      • 消息状态cas减少重复投递同一条消息。投递环节发现状态不符合要求,将被计入异常表。
    • 针对延时队列的投递
      • 缓存去重机制减少重复投递的可能性(基于消息库id而非业务层面,所以业务层面仍有重复投递的问题,需要消费端实现幂等)
      • 基于redis的实现,利用lua脚本实现缓存和延时队列的一致性
    • 针对延时队列的消费
      • 基于redis的实现,利用RPOPLPUSH模拟ack机制
      • 故障恢复时处理未应答ack
  4. repository

    • 消息库的访问
  5. delay

    • 通用类,依赖load、porter等模块。
  6. rocketmq模块

    • 针对rocketmq平台的实现
    • 使用rockemq事务消息,保证消息投递成功(保证消息状态的更新和投递成功与否的一致性)
    • 外部化配置封装,方便快速接入生产消费者
    • 故障消息记录机制

延时队列元素存取实现

  • redisson延时队列实现要点说明

    • redission延时队列基于redis的两个list、一个zset结合实现

      参考博文聊聊redisson的DelayedQueue 与 RDelayedQueue源码

    • 生产者同时投递消息到消息表(list)和计时表zset,如果推送消息处于zset第一个,则向指定频道推送timeout消息

      详细可参考 org.redisson.RedissonDelayedQueue#offerAsync(V, long, java.util.concurrent.TimeUnit)

    • 计时表zset存储附带延时与消息key信息,由调度任务定时的将到期元素原子地移到就绪列表,调度也由订阅的timeout消息触发

    • list存储就绪元素,消费者线程阻塞读取此列表数据进行消费

优化点

  1. 投递时,通过改造lua脚本加入缓存去重机制,保证缓存与消息表的一致性

    lua脚本只能保证命令的原子性无法保证事务。所以脚本一定要正确。

    lua脚本将先前两次IO减少为一次,大大降低了延时,减少了不一致的可能。

    疑问点:

    ​ lua脚本执行到一半掉电,如果redis每条指令都持久化,可能仍会导致数据不一致吗?

    即使以上会不一致,但是缓存设定了时间,最差情况下仍会在失效时间后恢复业务。

  2. 消费take时使用BRPOPLPUSH命令将元素暂存到consumingQueue中,待消费成功后删除(ack机制)。在应用启动porter线程时,也会优先将consumingQueue重新放入就绪队列中重新消费保证百分百消费成功。

  • java DelayQueue实现

    • 缺点较多,只能用在低数据量场景。不做具体介绍。有兴趣可以参考项目中 LocalCacheDelayMsgQueue实现。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值