SpringBoot redis系列 -延时队列(1)
背景
PS:笔者所在公司目前业务比较简单,相对项目架构也比较简单,暂时未有引入MQ等消息中间件,但是某天突然收到一个需求,需要在用户关注了我们的公众号之后,延迟几秒钟给用户在发送几条消息。最初考虑用要不DelayQueue或者定时线程池ScheduledThreadPoolExecutor走一波?感觉都不够优雅,刚好项目中有用到Redis,干脆就用Redis做个延时队列,也方便以后复用。当然,Redis实现的队列不是专业的MQ 对消息可靠性有高度要求的话,并不建议使用。比较简单的业务场景下还是可以用来异步延时解耦的。
正文
延迟队列可以通过Zset(有序列表实现),Zset类似于java中SortedSet和HashMap的结合体,它是一个Set结构,保证了内部value值的唯一,同时他还可以给每个value设置一个score作为排序权重,Redis会根据score自动排序,我们每次拿到的就是最先需要被消费的消息,利用这个特性我们可以很好实现延迟队列。
spring:
application:
name: redis-example
redis:
host: localhost
port: 6379
# redis有16个库 默认选择第0个使用
database: 0
password:
# 端口给个0 代表随机选择一个未被使用端口
server:
port: 0
封装一个统一的Message类,方便统一管理所有延迟消息格式
package com.smalljop.redis.example.queue;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/**
* @description: 消息统一封装类
* @author: smalljop
* @create: 2020-01-03 10:20
**/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Message {
/**
* 消息唯一标识
*/
private String id;
/**
* 消息渠道 如 订单 支付 代表不同业务类型
* 为消费时不同类去处理
*/
private String channel;
/**
* 具体消息 json
*/
private String body;
/**
* 延时时间 被消费时间 取当前时间戳 延迟时间
*/
private Long delayTime;
/**
* 创建时间
*/
private LocalDateTime createTime;
}
封装一个延时队列工具类 负责维护队列 提供常用操作
package com.smalljop.redis.example.queue;
import com.fasterxml.ja