文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Redis实现延迟队列的方案总结

2024-11-29 23:00

关注

1、通过过期key通知实现

图片

 实现思路:首先开启redis的key过期通知,然后在业务中给key设置过期时间,到了过期时间后redis会自动的将过期的key消息推送给监听者,从而实现延迟任务。

核心的代码实现:

#1、开始redis的过期通知
notify-keyspace-events Ex


#2、监听redis的过期key
@Component
@Slf4j
public class RedisExpireKeyService extends 
                  KeyExpirationEventMessageListener {


    
    public RedisExpireKeyService(RedisMessageListenerContainer listenerContainer) {
        super(listenerContainer);
    }


    
    @Override
    public void onMessage(Message message, byte[] pattern) {
        String expireKey = message.toString();


        //执行具体的业务
        System.out.println("监听到key=" + expireKey + ",已经过期");
    }




}

生产环境是不推荐使用此方案,原因Redis 的过期策略采用的是惰性删除和定期删除相结合的方式,redis并不保证 key 在过期时会被立即删除操作,此方案适用于平时自己项目练习的时候使用。

2、通过Zset数据类型+定时任务实现

图片

    实现思路:ZSet 是一种有序集合类型,它可以存储不重复的元素,并且给每个元素赋予一个 double 类型的排序权重值(score),所以可以将元素的过期时间作为分值,通过定时任务扫描的方式判断是否达到过期时间,从而实现延迟队列。

    核心的代码实现:

#使用xxl-job
@JobName("consumerTaskJob")
public void consumerTaskJob() {
   String expireKey = "ExPIRE_KEY";
   try {
       //获取当前时间
        double currentTime = System.currentTimeMillis();
        //获取超时的数据
        Set expiredMemberSet = redisTemplate.opsForZSet().rangeByScore(expireKey, Double.MIN_VALUE, currentTime);


        //过期key
        for (String expiredMember : expiredMemberSet) {
            //todo 做实际的延迟任务
            
            //从ZSet中移除数据
            redisTemplate.opsForZSet().remove(expireKey, expiredMember);
        } 
       } catch (Exception e) {
          log.error("数据处理失败",e);
       }
    }

Zset+定时任务的实现延迟任务的方式虽然比监听过期key方案合理一些,但是它还是存在一定的缺陷,如无重试机制、延迟时间固定化(依赖定时任务的执行时间)、不适用于大规模的延迟任务。

3、Redisson实现延迟队列

Redisson是一个操作Redis的 Java 客户框架,它提供了RDelayedQueue 接口和 RQueue 接口可以实现延迟队列(Redisson 提供的延迟队列底层也是基于 Zset 数据结构实现的)。

    核心的代码实现:

#1、添加依赖

 org.redisson
 redisson
 3.16.0 



#2、添加数据到队列中
//创建RedissonClient实例
RedissonClient redissonClient = Redisson.create();
//创建阻塞队列
RBlockingDeque queue = redissonClient.getBlockingDeque("delayQueue");
//创建延迟队列并关联到阻塞队列
RDelayedQueue delayedQueue = redissonClient.getDelayedQueue(queue);
//添加延迟任务
delayedQueue.offer("Task1", 5000, TimeUnit.MILLISECONDS);


#3、消费数据
while (true) {
    try {
          //获取并移除队首元素,如果队列为空,则阻塞等待
          String task = queue.take();
          System.out.println("Task: " + task);
       } catch (Exception e) {
          log.error("消费失败",e);
     }
}

总结:Redis实现的延迟队列适用于处理一些比较简单的业务,如发送邮件、发送通知等,对于复杂的业务不适用于Redis的延迟任务方案。

来源:龙虾编程内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯