Spring Boot + Redis 实现延时队列,写得太好了

本文详细介绍了如何使用Spring Boot结合Redis构建延时队列,包括业务流程、对象定义、任务状态管理、对外接口设计以及具体实现,包括任务池、延迟桶和待完成任务队列的实现细节,最后提供了测试请求的示例。
摘要由CSDN通过智能技术生成

业务流程

首先我们分析下这个流程

  1. 用户提交任务。首先将任务推送至延迟队列中。
  2. 延迟队列接收到任务后,首先将任务推送至job pool中,然后计算其执行时间。
  3. 然后生成延迟任务(仅仅包含任务id)放入某个桶中
  4. 时间组件时刻轮询各个桶,当时间到达的时候从job pool中获得任务元信息。
  5. 监测任务的合法性如果已经删除则pass。继续轮询。如果任务合法则再次计算时间
  6. 如果合法则计算时间,如果时间合法:根据topic将任务放入对应的ready queue,然后从bucket中移除。如果时间不合法,则重新计算时间再次放入bucket,并移除之前的bucket中的内容
  7. 消费端轮询对应topic的ready queue。获取job后做自己的业务逻辑。与此同时,服务端将已经被消费端获取的job按照其设定的TTR,重新计算执行时间,并将其放入bucket。
  8. 完成消费后,发送finish消息,服务端根据job id删除对应信息。

对象

我们现在可以了解到中间存在的几个组件

  • 延迟队列,为Redis延迟队列。实现消息传递
  • Job pool 任务池保存job元信息。根据文章描述使用K/V的数据结构,key为ID,value为job
  • Delay Bucket 用来保存业务的延迟任务。文章中描述使用轮询方式放入某一个Bucket可以知道其并没有使用topic来区分,个人这里默认使用顺序插入
  • Timer 时间组件,负责扫描各个Bucket。根据文章描述存在多个Timer,但是同一个Timer同一时间只能扫描一个Bucket
  • Ready Queue 负责存放需要被完成的任务,但是根据描述根据Topic的不同存在多个Ready Queue。

其中Timer负责轮询,Job pool、Delay Bucket、Ready Queue都是不同职责的集合。

任务状态

  • ready:可执行状态,
  • delay:不可执行状态,等待时钟周期。
  • reserved:已被消费者读取,但没有完成消费。
  • deleted:已被消费完成或者已被删除。

对外提供的接口

额外的内容

  1. 首先根据状态状态描述,finish和delete操作都是将任务设置成deleted状态。
  2. 根据文章描述的操作,在执行finish或者delete的操作的时候任务已经从元数据中移除,此时deleted状态可能只存在极短时间,所以实际实现中就直接删除了。
  3. 文章中并没有说明响应超时后如何处理,所以个人现在将其重新投入了待处理队列。
  4. 文章中因为使用了集群,所以使用redis的setnx锁来保证多个时间循环处理多个桶的时候不会出现重复循环。这里因为是简单的实现,所以就很简单的每个桶设置一个时间队列处理。也是为了方便简单处理。关于分布式锁可以看我之前的文章里面有描述。

实现

现在我们根据设计内容完成设计。这一块设计我们分四步完成

任务及相关对象

目前需要两个对象,一个是任务对象(job)一个负责保存任务引用的对象(delay job)

任务对象

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Job implements Serializable {

    /**
     * 延迟任务的唯一标识,用于检索任务
     */
    @JsonSerialize(using = ToStringSerializer.class)
    private Long id;

    /**
     * 任务类型(具体业务类型)
     */
    private String topic;

    /**
     * 任务的延迟时间
     */
    private long delayTime;

    /**
     * 任务的执行超时时间
     */
    private long ttrTime;

    /**
     * 任务具体的消息内容,用于处理具体业务逻辑用
     */
    private String message;

    /**
     * 重试次数
     */
    private int retryCount;
    /**
     * 任务状态
     */
    private JobStatus status;
}
复制代码</
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值