【Redis】Redis结合SpringBoot实现延时队列

1.场景

不知道各位开发者们在开发过程中有没有遇到过这样的场景,就是有一条数据进来了,要设置超时时间,比如我这里有一条待办的数据,48小时还未处理的话,这条数据要变成超时的状态,此时不光要修改状态,还要发信息通知他消息超时未处理。
此时,你有如下的解决思路:

  • 定时任务:每隔多长时间轮询一遍数据库,根据创建时间进行判断,超过48小时的进行处理,缺点显而易见,超时处理的不及时,时间设置的过短,可能上一次还没遍历完,下一次又开始了,时间设置过长,可能早就超时了,直到现在你才提醒用户超时

除此之外还有很多种,比如数据库写个触发器,通过MQ等等,但是这些都有很大的缺点。

2.Redis延时队列

2.1 引入依赖

   <dependency>
         <groupId>org.redisson</groupId>
         <artifactId>redisson</artifactId>
         <version>3.16.4</version>
   </dependency>

2.2 注入RedisClient

@Configuration
public class RedissonConfig {

    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.port}")
    private String port;
    @Value("${spring.redis.password}")
    private String password;
    @Value("${spring.redis.database}")
    private Integer database;


    @Bean()
    public RedissonClient redissonClient() {
        Config config = new Config();
        SingleServerConfig serversConfig = config.useSingleServer();
        serversConfig.setAddress("redis://" + host + ":" + port);
        if (StringUtils.isNotEmpty(password)){
            serversConfig.setPassword(password);
        }
        serversConfig.setDatabase(database);
        return Redisson.create(config);
    }

}

3. 注入延时队列Bean

@Configuration
public class RedissonQueueConfig {

    private final String queueName = "queue";

    @Bean
    public RBlockingQueue<String> rBlockingQueue(RedissonClient redissonClient) {
        return redissonClient.getBlockingDeque(queueName);
    }

    @Bean(name = "rDelayedQueue")
    public RDelayedQueue<String> rDelayedQueue(RedissonClient redissonClient,
                                               @Qualifier("rBlockingQueue") RBlockingQueue<String> blockingQueue) {
        return redissonClient.getDelayedQueue(blockingQueue);
    }

}

4.编写方法

1.Service

public interface DelayQueue {

    public Boolean offer(Object object);

    public void offer(Object object, Long time, TimeUnit timeUnit);

    public void offerAsync(Object object, Long time, TimeUnit timeUnit);

    public Boolean offerAsync(Object object);

}

2.Service实现类

@Component
public class RedissionDelayQueue implements DelayQueue{

    @Resource(name = "rDelayedQueue")
    private RDelayedQueue<Object> rDelayedQueue;


    @Override
    public Boolean offer(Object object) {
        return rDelayedQueue.offer(object);
    }

    @Override
    public void offer(Object object, Long time, TimeUnit timeUnit) {
        rDelayedQueue.offer(object, time, timeUnit);
    }

    @Override
    public void offerAsync(Object object, Long time, TimeUnit timeUnit) {
        rDelayedQueue.offerAsync(object, time, timeUnit);
    }

    @Override
    public Boolean offerAsync(Object object) {
        boolean flag = false;
        RFuture<Boolean> rFuture = rDelayedQueue.offerAsync(object);
        try {
            flag = rFuture.get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
        return flag;
    }
}

5.开启一个线程,持续监听

    @Resource(name = "rBlockingQueue")
    private RBlockingQueue<Object> rBlockingQueue;
 //延时队列,设置状态为已超时
    @PostConstruct
    public void take(){
        new Thread(() -> {
            while(true) {
                try {
                    Object obj = rBlockingQueue.take();
                    System.out.println(obj);
                } catch (InterruptedException e){
                    e.printStackTrace();
                }
            }
        }).start();
    }
	

6. 调用

接下来只要调用,RedissionDelayQueue 中的方法就可以实现,过期的任务会通过rBlockingQueue.take();返回

    @Autowired
    private DelayQueue delayQueue;

	public void test(){
	  delayQueue.offer("test",10L, TimeUnit.SECONDS);
	}

上述代码缩写,take()方法将在10S后返回过期的内容test

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JeffHan^_^

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值