应用开发

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

时间:2010-12-5 17:23:32  作者:数据库   来源:IT科技类资讯  查看:  评论:0
内容摘要:redis是我们项目开发中常见的技术中间件,它除了可以实现常见的分布式锁和分布式缓存功能之外,还可以帮助我们实现很多的功能,如延迟队列。下面介绍几种redis常见的实现延迟队列的方案。1、通过过期ke

 redis是现延我们项目开发中常见的技术中间件,它除了可以实现常见的迟队分布式锁和分布式缓存功能之外,还可以帮助我们实现很多的总结功能,如延迟队列。现延下面介绍几种redis常见的迟队实现延迟队列的方案。

1、总结通过过期key通知实现

图片

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

核心的迟队代码实现:

复制#1、开始redis的总结过期通知 notify-keyspace-events Ex #2、监听redis的现延过期key @Component @Slf4j public class RedisExpireKeyService extends KeyExpirationEventMessageListener { /** * Creates new {@link MessageListener} for {@code __keyevent@*__:expired} messages. * * @param listenerContainer must not be {@literal null}. */ public RedisExpireKeyService(RedisMessageListenerContainer listenerContainer) { super(listenerContainer); } /** * 监听过期的key * */ @Override public void onMessage(Message message, byte[] pattern) { String expireKey = message.toString(); //执行具体的业务 System.out.println("监听到key=" + expireKey + ",已经过期"); } }1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.36.37.38.

生产环境是迟队不推荐使用此方案,原因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<String> 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); } }1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.

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

3、Redisson实现延迟队列

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

    核心的代码实现:

复制#1、添加依赖 <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.16.0</version> </dependency> #2、添加数据到队列中 //创建RedissonClient实例 RedissonClient redissonClient = Redisson.create(); //创建阻塞队列 RBlockingDeque<String> queue = redissonClient.getBlockingDeque("delayQueue"); //创建延迟队列并关联到阻塞队列 RDelayedQueue<String> 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); } }1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.

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

IT技术网
copyright © 2025 powered by 编程之道  滇ICP备2023006006号-34sitemap