Grape是基于Redis实现的一个高并发、高性能、高可用的分布式延迟任务系统。主要提供以下特性:
- 任务具备延时、过期重试、重试次数、预留时间等功能。
- 通过Vert.x异步IO提供高性能 HTTP Restful API。
- 任务调度支持毫秒级精度,0毫秒延迟,Redis损耗小。
- 具备横向扩展能力,丰富的业务和性能指标监控接口。
什么是延迟任务
想必大家都在网上购过物,比如,你在淘宝上买了件商品,收到货物后,即使你不主动去点 “确认收货”,经过若干天后,系统会自动确认收货,完结订单。
这是怎么做到的呢?其实,这个背后隐藏着一个常用技术,就是延迟任务。顾明思议,我们把需要延迟执行的任务叫做延迟任务。
请注意,延迟任务不是定时任务,它们之间是有显著的区别:
- 定时任务有明确的触发时间,延迟任务没有。
- 定时任务有执行周期,而延迟任务在某事件触发后一段时间内执行,没有执行周期。
- 定时任务一般执行的是批处理操作的任务,而延迟任务一般是针对单个处理操作的任务。
延迟任务典型场景
使用延迟任务的典型场景有以下这些:
- 红包 24 小时未被查收,需要执行退款业务。
- 提交订单 30 分钟后,用户如果没有付钱,系统需要自动取消订单,归还库存。
- 直播时间快到了,需要给关注的用户发送消息,提醒上线。
- 支付完成后,需要异步回调通知业务系统的支付完成状态,在至少一次的QoS要求下,需要按指数幂退时间间隔延迟执行回调。
仔细审查这些业务场景,会发现每个业务处理都是在一定时间后执行特定的任务,而触发的时间不是固定的,如果做成定时任务来处理会很麻烦,而且时效和性能无法很好的保证。因此,创建一个解决此类问题的延迟任务系统才是最佳实践。
延迟任务系统的特性
- 延迟任务的生产和消费需要支持高并发、高性能、高可用。延迟任务的提交通常参与到核心的业务流程中,如果不能保证并发和性能,将对核心业务有影响。
- 延迟任务的生产需要支持重复提交,很多场景下可能会存在重试的情况。
- 延迟任务的消费需要支持可靠消费,也就是说要需要明确的知道是否成功执行了任务。通常,这需要系统在消费时暂存延迟任务信息,在执行成功后提交反馈。
- 延迟任务具备延时、自动重试、优先级等功能。
- 延迟任务系统需要具备横向扩展能力,丰富的业务和性能指标监控能力。
Grape的核心概念
-
Job :业务定义的延迟任务,有以下属性:
- id,任务ID,由业务系统指定,全局唯一。
- dtr (delay to run),任务延时运行时间,单位是毫秒。
- ttr (time to run),任务预期执行时间,单位是毫秒。超过 ttr 则触发任务重试。
- noe (number of executions),任务执行次数,默认从0开始,消费一次自增一。业务系统可以根据该属性做业务处理,如指数幂退调用等。
- data (job content),任务内容,字节数组。业务系统可以提交一些任务执行需要的参数,避免再次查询数据库准备数据。
-
Tube :同一个主题的延迟任务队列,用于区分和管理不同业务分组的延迟任务。
-
Broker :延迟队列代理,用于管理Tube集合的运行。
-
Server :Grape服务实例,为指定 namespace 的Broker提供 Restfull 的 Job API、Tube API、管理API和管理UI。
整体架构设计
Grape 是一个无状态的HTTP服务,很容易横向扩展。业务系统可以通过7层负载均衡器访问Grape-Server集群。
-
Grape-Server主要由API处理器和Broker组件构成。
- Broker内部由Scheduler和Tube组件构成。
- Scheduler负责发现和加载Tube实例,以便更多的Broker实例分担Tube实例的管理压力,同时对外提供API服务。
- Tube组件是延迟任务的管理器,其内部维护了3个Sorted Set队列:Deleay Queue、Remain Queue、Failed Queue。根据延迟任务的生命状态机制,任务在各个队列之间流动。
- Redis存储主要包含了三类数据,分别是tube的名称集合、tube的队列模型和延迟任务模型。
- tube的名称集合,是一个Set类的集合,代表当前由多少可用的延迟队列。
- tube的队列模型,3个队列都是Sorted Set数据结构,Key是tube名称,数据是以延迟时间排序的任务ID。
- 延迟任务模型,每个任务是一个HashMap结构的数据,Key是任务ID,Value是任务的各个属性。
任务生命周期
Grape借鉴了Beanstalkd的任务管理机制,因此在Grape中,延迟任务可能处于四种状态之一:“delay”、“ready”、“remain”或“failed”。围绕任务状态的迁移动作,满足了很多通用场景对延迟任务的诉求。
-
delay 状态,业务系统生成(produce)延迟任务后进入该状态。处于该状态的任务可以被删除(delete)。当前时刻大于任务延时后,任务迁移至ready状态。
-
ready 状态,业务系统生成(produce)延时为0毫秒的延迟任务进入该状态,或已过了延时的延迟任务进入该状态。进入该状态的任务可以被消费。消费任务(consume)将进入remain状态。
-
remain 状态,任务在消费期间会出现4种情况:
- 任务执行时间操过了ttr,或者执行任务的线程跑飞、业务进程宕机等异常情况下,任务会被调度到ready状态,使得任务可以被再次消费。
- 任务执行很顺利,但还没有拿到期望的结果,希望能再次重试,那么可以指定延时并释放(release)任务至delay状态。
- 任务执行很顺利,拿到了期望的结果,那么可以结束(finish)任务。
- 任务执行失败了,暂时无法处理,可能需要人工介入,可以先雪藏(bury)起来,则任务迁移至failed状态。
-
failed 状态,该状态的任务通常为异常任务,可通过查看(peek)任务来决策,如果需要继续执行,则打回(kick)到delay状态,如果不在需要执行,则可丢弃(discard)掉任务。
评论