写点什么

微服务中台技术之延迟中心实践

作者:小江
  • 2021 年 11 月 14 日
  • 本文字数:929 字

    阅读完需:约 3 分钟

微服务中台技术之延迟中心实践

背景

在电商业务场景中,我们会经常遇到需要使用延迟服务,比如用户下单后需要在一定时间内完成支付,物流开始一段时间后发送通知等,这些场景的特点是请求不是立即生效,而是在延时一段时间后再发出请求执行,即延迟执行。

技术方案

为了达到延迟执行的目的,我们需要暂存请求,然后定时轮询延时是否到期,到期则取出延时任务执行。在设计目标上,要保证延时任务不丢失,同时查询效率要高。为此,我们实现了以redis + kafka 的架构,既保证了延时任务的可靠性,还兼顾了轮询效率,如下图所示:

延时中心系统架构

其中,

  • redis 主要是使用其 zset 机制,利用其排序功能快速找出延时到期的任务

  • kafka 主要是用来保存到期任务,确保到期任务能按时执行,不会丢失


下面我们简要介绍下整个执行流程:

  1. 用户调用延时注册接口注册延时任务(已提前申请好业务标识与回调地址等,存于配置中心组件)

  2. 延时中心收到请求后,将其写入 redis zset(score 为到期时间)

  3. redis worker 定时轮询(e.g. 30s, 取决于延时精度),将到期任务(score 小于当前时间的任务)发送到 kafka 指定 topic

  4. kafka worker 消费指定 topic,取出到期任务,通过 callback 地址回调业务方接口,回调成功则 commit 该消息


注意事项

上面的方案在实施过程中还需要注意以下几点:

  1. 在查询 redis 获得到期任务并发送到 kafka 后,需要删除 redis 中对应的延时任务,否则会造成延时任务重复执行。具体方案是增加重试机制,删除 redis 失败的任务会丢到 kafka retry topic,消费后重新执行删除。

  2. 为了保证延迟中心服务的高可用,一般是多实例部署,因此在轮询 redis 时会出现争抢,引起并发问题,因此需要引入分布式锁解决并发轮询问题(e.g. redisson 组件或者 zk 实现分布式锁)。

  3. 在整个设计方案中,我们保证的延时任务的可靠性与轮询的精度和效率,但不保证延时任务的重复投递(虽然我们通过失败重试机制尽可能保证减少重复投递的可能,但无法完全避免重复投递,我们保证的是最少投递一次),因此业务方回调接口需要保持幂等。


总结与思考

本文基于redis + kafka实现了一个具备高可用的延迟中心服务,上线后运行情况良好,下一步从反馈中将持续优化该服务,比如支持 dubbo 接口注册延时任务,支持业务方自定义消息队列(方便自行消费),采用异步方式回调业务方接口等。

大家有什么好的想法或者意见,欢迎留言探讨~

发布于: 2021 年 11 月 14 日阅读数: 18
用户头像

小江

关注

~做一个安静的码男子~ 2019.02.11 加入

软件工程师,目前在电商公司做研发效能平台,中间件维护开发相关工作

评论

发布
暂无评论
微服务中台技术之延迟中心实践