Redis--SpringBoot Redis实现延时队列

本文详细介绍了如何在SpringBoot项目中利用Redis创建延时队列,包括配置pom.xml、application.yml,定义DelayTask模型,实现RedisDelayQueue和ConsumerThread,通过RedisController设置延时任务入口,以及CommonResult公共返回对象。最后,讲解了项目的安装部署和测试步骤,读者可以通过访问特定URL进行测试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第一步:pom.xml

        <!-- redis -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

第二步:application.yml

server:
  port: 8081
  servlet:
    context-path: /

spring:
  # redis非关系型数据库
  redis:
    host: 服务器ip
    port: 6379
    password: 密码
    jedis:
      pool:
        # 连接池最大连接数(使用负值表示没有限制)
        max-active: 8
        # 连接池最大阻塞等待时间(使用负值表示没有限制)
        max-wait: -1
        # 连接池中的最大空闲连接
        max-idle: 500
        # 连接池中的最小空闲连接
        min-idle: 0
    lettuce:
        shutdown-timeout: 0

第三步:DelayTask延时任务模型

/**
 * @Author ben
 * @Description 延时任务模型
 * @Date 上午10:59 2022/3/4
 **/
@Data
public class DelayTask<T> {
    /**
     * 消息id
     */
    private String id;
    /**
     * 任务名称
     */
    private String taskName;
    /**
     * 具体任务内容
     */
    private T msg;
}

第四步:RedisDelayQueue延时队列

/**
 * @Author ben
 * @Description redis延时队列
 * @Date 上午11:05 2022/3/4
 **/
public class RedisDelayQueue<T> {
    /**
     * 延迟队列名称
     */
    private String delayQueueName = "delayQueue";


    private RedisTemplate redisTemplate;

    // 传入redis客户端操作
    public RedisDelayQueue(RedisTemplate redisTemplate, String delayQueueName)
    {
        this.redisTemplate = redisTemplate;
        this.delayQueueName = delayQueueName;
    }
    /**
     * 设置延迟消息
     */
    public boolean setDelayTasks(T msg, long delayTime) {
        DelayTask<T> delayTask = new DelayTask<>();
        delayTask.setId(UUID.randomUUID().toString());
        delayTask.setMsg(msg);
        Boolean addResult = redisTemplate.opsForZSet().add(delayQueueName, JSONObject.toJSONString(delayTask), System.currentTimeMillis() + delayTime);
        if(addResult)
        {
            System.out.println("添加任务成功!"+JSONObject.toJSONString(delayTask)+"当前时间为"+ LocalDateTime.now());
            return true;
        }
        return false;
    }
    /**
     * 监听延迟消息
     */
    public void listenDelayLoop() {
        System.out.println("线程名称:"+ Thread.currentThread().getName());
        System.out.println("线程id:"+ Thread.currentThread().getId());
        while (true) {
            // 获取一个到点的消息
            Set<String> set = redisTemplate.opsForZSet().rangeByScore(delayQueueName, 0, System.currentTimeMillis(), 0, 1);

            // 如果没有,就等等
            if (set.isEmpty()) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 继续执行
                continue;
            }
            // 获取具体消息的key
            String it = set.iterator().next();
            // 删除成功
            if (redisTemplate.opsForZSet().remove(delayQueueName, it) > 0) {
                // 拿到任务
                DelayTask delayTask = JSONObject.parseObject(it, DelayTask.class);
                // 后续处理
                System.out.println("消息到期;"+delayTask.getMsg().toString()+",到期时间为"+ DateUtil.formatAsDatetime(new Date()));
            }
        }
    }
}

第五步:CustomerThread 消费者线程

/**
 * @Classname CustomerThread
 * @Description 消费者线程
 * @Date 2022/3/4 23:38
 * @Created ben
 */
public class CustomerThread extends Thread {
    private RedisTemplate redisTemplate;
    public CustomerThread(RedisTemplate redisTemplate){
        this.redisTemplate = redisTemplate;
    }
    @Override
    public void run(){
        RedisDelayQueue queue = new RedisDelayQueue(redisTemplate,"下单未付款,1min后自动取消!");
        queue.listenDelayLoop();
    }
}

第六步:RedisController延时任务入口

/**
 * @Classname RedisController
 * @Description redis延时任务入口
 * @Date 2022/3/4 22:41
 * @Created ben
 */
@RestController
@RequestMapping("/redis")
public class RedisController {
    @Autowired
    private RedisTemplate redisTemplate;
    public boolean customerThread = false;

    @RequestMapping("/createDelayTasks")
    public CommonResult createDelayTasks(@RequestParam(value = "orderNumber") String orderNumber){
        String msg = "订单号:" + orderNumber + ",下单时间:"+ DateUtil.formatAsDatetime(new Date());
        RedisDelayQueue queue = new RedisDelayQueue(redisTemplate,"下单未付款,1min后自动取消!");
        boolean result = queue.setDelayTasks(msg, 60000);
        if (!customerThread){
            customerThread = true;
            CustomerThread thread = new CustomerThread(redisTemplate);
            thread.start();
        }
        if (result){
            return new CommonResult(true,"下单成功,未付款,1min后自动取消订单!");
        }
        return new CommonResult(false,"下单失败!");
    }

}

第七步:CommonResult公共返回对象

/**
 * @Author ben
 * @Description 公共返回对象
 * @Date 上午11:40 2022/1/14
 **/
@Data
public class CommonResult<T> implements Serializable {
    private boolean isucceed;
    private T data;
    public CommonResult(boolean isucceed,T data) {
        this.isucceed = isucceed;
        this.data = data;
    }
    public CommonResult(){

    }
}

第八步:install

  • install后的jar包,就在项目路径的target下.

第九步:部署服务器,并启动项目

第十步:访问url,并测试

  • ip:端口号/redis/createDelayTasks?orderNumber=1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值