延迟发奖 - 基于循环链表的伪延时消息队列

最近做了一个下单返金币的小功能,又造了个小轮子。由于下单后存在退货的可能,因此要求用户下单后先发放一个冻结奖励,在一定天数之后如果没有退款,自动发放真实奖励。

 

理论

此处使用了循环队列与线程池做了一个伪延时消息队列,理论来自@58沈剑,基本实现如下:

MQ的consumer在拿到消息后,获得需要做实际操作的时间,计算与当前时间的时间差。由于本例实际应用中对时间要求不是特别精确,因此采用60个unit的循环队列,worker每间隔1分钟移动到下一个unit。如果对时间要求比较高,可以采用3600个unit的循环队列,worker每1秒前进一格。

遍历当前unit所包含的job,如果circularNum为0,应当立即执行操作,为了保证worker不会因执行业务逻辑使得移动的时间间隔与1分钟差距过大,启动子线程执行实际操作过程;如果circularNum>0,则将其减一,继续判断下一个job。worker等待1min后移动到下一格,重复上述操作。

由于线程数目较多,采用线程池进行管理。

 

安全机制

防止重复放置 - 循环队列的每个unit采用Set存储job,防止消息重复放入。

防止重复处理 - 从MQ中拿到消息时,将消息存储在DB中,状态置0,直到实际操作完毕,状态置1。在实际下发前,先判断当前job状态是否为0,如果是已操作过的消息,跳过执行并将其在队列中删除。

Redis - 为了防止服务重启时的数据丢失,将整个循环队列存储在redis中,每次启动后先从redis中恢复,如果没有数据,则创建一个新队列。

定时扫描 - 为了防止消息在放入循环队列的过程中失败或其他异常情况,使用一个独立的worker定时扫描,如果存在已过应下发的时间但是状态为0的记录,立即恢复。

单个步骤事务处理 - 此步骤依赖了团队已有的其他服务,单个步骤失败时(如保存记录),会进行5次重试。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值