当前位置: 首页 > news >正文

Java实现Redis延时队列

“如何实现Redis延时队列”这个面试题应该也是比较常见的,解答如下:
使用sortedset(有序集合) ,拿时间戳作为 score ,消息内容作为key 调用 zadd 来生产消息,消费者用zrangebyscore 指令获取 N 秒之前的数据轮询进行处理。

目录

  • 实现思路
  • 引入Jedis
  • 指令简介
    • zadd
    • zrem
    • zrangeByScore
  • Java实现Redis延时队列

实现思路

Java实现Redis延时队列,首先要了解何为延时队列,即可以将消息存储在队列中,并在指定的延时时间后再将消息出队。这种队列在很多场景下都非常有用,例如消息延时处理,延时确认(订单确认) 等,参考以上解答,思路应该拆分:
首先需要有个延时队列,该队列是通过一定顺序(当前时间戳+延时时间)排序的(即优先取到延时时间已结束的数据),然后消费者端就需要获取到队列中延时时间靠前结束的数据(即当前时间戳+延时时间靠前)。

引入Jedis

<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.7.0</version>
</dependency>

指令简介

zadd

zadd命令用于将一个成员Score值加入到有序集合中。Score值可以是整数或者浮点数。如果有序集合中已经存在相同的成员,那么旧成员将被替代。
语法:ZADD key Score member [Score2 member2 …]
示例:ZADD students 100 alice 或 ZADD students 80 alice 90 bob (添加单个或多个情况)

zrem

zrem命令用于从有序集合中移除一个或多个成员。该命令接收两个参数:第一个参数是要操作的有序集合的键,第二个参数是将要移除的成员的值。
语法:ZREM key member [member …]
示例:ZREM students alice

zrangeByScore

zrangeByScore命令用于获取分数在指定范围内的所有成员。
语法:ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
参数说明:
key:Redis中的键。
min:最小分数。
max:最大分数。
WITHSCORES:可选参数,如果设置为true,则返回分数以及成员。
LIMIT:可选参数,用于限制返回的成员数量。
offset:偏移量,从第几个成员开始。
count:限制返回的成员数量。
返回值:
按照分数升序返回成员列表。
如果设置了LIMIT参数,则返回限制数量的成员。
示例:ZADD ZRANGEBYSCORE students 80 90 WITHSCORES

Java实现Redis延时队列

核心部分,消息队列工具类

import redis.clients.jedis.Jedis;
import java.util.Set;public class DelayQueueWithRedis {private Jedis jedis;private String queueKey;public DelayQueueWithRedis(Jedis jedis, String queueKey) {this.jedis = jedis;this.queueKey = queueKey;}// 添加消息到延迟队列public void push(String message, long delaySeconds) {// 计算消息的分数,这里使用消息进入队列的时间加上延迟时间long score = System.currentTimeMillis() / 1000 + delaySeconds;//向有序集合添加一个成员,并设置其分数jedis.zadd(queueKey, score, message);}// 获取并消费一条消息public String pop() {while (true) {long now = System.currentTimeMillis() / 1000;// 只获取分数在0到当前时间的元素Set<String> messages = jedis.zrangeByScore(queueKey, 0, now, 0, 1);if (messages.isEmpty()) {System.out.println("No messages");// 没有可消费的消息,休眠一会儿继续尝试try {Thread.sleep(500);} catch (InterruptedException e) {Thread.currentThread().interrupt();break;}} else {String message = messages.iterator().next();// 从有序集合中移除一个成员jedis.zrem(queueKey, message);return message;}}return null;}
}

生产者端测试

import redis.clients.jedis.Jedis;/*** @Author: zhangximing* @Email: 530659058@qq.com* @Date: 2024/2/19 16:53* @Description: 生产者端测试*/
public class MainP {public static void main(String[] args) {Jedis jedis = new Jedis("localhost",6379);DelayQueueWithRedis delayQueue = new DelayQueueWithRedis(jedis, "delay_queue");// 添加延时消息delayQueue.push("message1", 5);delayQueue.push("message2", 10);delayQueue.push("message3", 8);}}

消费者端测试

import redis.clients.jedis.Jedis;/*** @Author: zhangximing* @Email: 530659058@qq.com* @Date: 2024/2/19 16:51* @Description: 消费者端测试*/
public class MainC {public static void main(String[] args) {Jedis jedis = new Jedis("localhost",6379);DelayQueueWithRedis delayQueue = new DelayQueueWithRedis(jedis, "delay_queue");// 消费延时消息while (true) {String message = delayQueue.pop();if (message != null) {System.out.println("Consumed: " + message);}}}
}

测试结果:数据在延时指定时间后才正常打印
在这里插入图片描述

相关文章:

  • 【机器学习】是什么?
  • 3.测试教程 - 基础篇
  • .netcore 6.0/7.0项目迁移至.netcore 8.0 注意事项
  • AI智能制作ER图技术革新:itBuilder引领数据库设计新篇章
  • 记一次重大的问题解决
  • kali xrdp
  • STM32—触摸键
  • 我们在SqlSugar开发框架中,用到的一些设计模式
  • 光学相干断层扫描(OCT)在 妇科诊断 中的革命性应用
  • 服务器遭受 DDoS 攻击的常见迹象有哪些?
  • C语言—自定义(构造)类型
  • igolang学习3,golang 项目中配置gin的web框架
  • 算法提升——LeetCode第385场周赛总结
  • 端口占用:Web server failed to start. Port XXX was already in use.原因分析-解决方案
  • RabbitMQ 网络分区处置策略配置
  • 「前端」从UglifyJSPlugin强制开启css压缩探究webpack插件运行机制
  • bearychat的java client
  • emacs初体验
  • Java知识点总结(JDBC-连接步骤及CRUD)
  • RxJS: 简单入门
  • vue从创建到完整的饿了么(18)购物车详细信息的展示与删除
  • 基于Android乐音识别(2)
  • 前端js -- this指向总结。
  • 前端存储 - localStorage
  • 区块链技术特点之去中心化特性
  • 一起来学SpringBoot | 第十篇:使用Spring Cache集成Redis
  • CMake 入门1/5:基于阿里云 ECS搭建体验环境
  • 格斗健身潮牌24KiCK获近千万Pre-A轮融资,用户留存高达9个月 ...
  • ​LeetCode解法汇总518. 零钱兑换 II
  • !!Dom4j 学习笔记
  • #Z2294. 打印树的直径
  • #常见电池型号介绍 常见电池尺寸是多少【详解】
  • #经典论文 异质山坡的物理模型 2 有效导水率
  • #我与Java虚拟机的故事#连载17:我的Java技术水平有了一个本质的提升
  • $.ajax中的eval及dataType
  • (C++20) consteval立即函数
  • (html转换)StringEscapeUtils类的转义与反转义方法
  • (离散数学)逻辑连接词
  • (四)搭建容器云管理平台笔记—安装ETCD(不使用证书)
  • *(长期更新)软考网络工程师学习笔记——Section 22 无线局域网
  • .bat批处理(九):替换带有等号=的字符串的子串
  • .NET : 在VS2008中计算代码度量值
  • .net使用excel的cells对象没有value方法——学习.net的Excel工作表问题
  • .net用HTML开发怎么调试,如何使用ASP.NET MVC在调试中查看控制器生成的html?
  • [ vulhub漏洞复现篇 ] JBOSS AS 5.x/6.x反序列化远程代码执行漏洞CVE-2017-12149
  • [1] 平面(Plane)图形的生成算法
  • [52PJ] Java面向对象笔记(转自52 1510988116)
  • [APIO2012] 派遣 dispatching
  • [AutoSAR 存储] 汽车智能座舱的存储需求
  • [BetterExplained]书写是为了更好的思考(转载)
  • [BUUCTF]-Reverse:reverse3解析
  • [C#]C#学习笔记-CIL和动态程序集
  • [CERC2017]Cumulative Code
  • [HarmonyOS]第一课:从简单的页面开始
  • [JS]数据类型