Redis使用ZSET实现消息队列使用总结一
转载请注明出处:
1.zset为什么可以做消息队列
zset做消息队列的特性有:
有序性:zset中所有元素都被自动排序。这让zset很适合用于有序的消息队列,因为可以根据一个或多个标准(比如消息的到达时间或优先级)按需检索消息。
元素唯一性:zset的每个元素都是独一无二的,这对于实现某些消息需求(比如幂等性)是非常有帮助的。
成员和分数之间的映射关系:有序集合中的每个成员都有一个分数,这样就可以将相同的数据划分到不同的 queue 中,以及为每个 queue 设置不同的延时。
高效的添加删除操作:因为zset会自动维护元素之间的顺序,所以在添加或删除元素时无需进行手动排序,从而能提升操作速度。
综上所述,Redis的zset天然支持按照时间顺序的消息队列,可以利用其成员唯一性的特性来保证消息不被重复消费,在实现高吞吐率等方面也有很大的优势。
2.zset实现消息队列的步骤
Redis的zset有序集合是可以用来实现消息队列的,一般是按照时间戳作为score的值,将消息内容作为value存入有序集合中。
实现步骤:
客户端将消息推送到Redis的有序集合中。
有序集合中,每个成员都有一个分数(score)。在这里,我们可以设成消息的时间戳,也就是当时的时间。
当需要从消息队列中获取消息时,客户端获取有序集合前N个元素并进行操作。一般来说,N取一个适当的数值,比如10。
需要注意的是,Redis的zset是有序集合,它的元素是有序的,并且不能有重复元素。因此,如果需要处理有重复消息的情况,需要在消息体中加入某些唯一性标识来保证不会重复。
3.使用jedis实现消息队列示例
Java可以通过Redis的Java客户端包Jedis来使用Redis,Jedis提供了丰富的API来操作Redis,下面是一段实现用Redis的zset类型实现的消息队列的代码。
import redis.clients.jedis.Jedis;
import java.util.Set; public class RedisMessageQueue {
private Jedis jedis; //Redis连接对象
private String queueName; //队列名字 /**
* 构造函数
* @param host Redis主机地址
* @param port Redis端口
* @param password Redis密码
* @param queueName 队列名字
*/
public RedisMessageQueue(String host, int port, String password, String queueName){
jedis = new Jedis(host, port);
jedis.auth(password);
this.queueName = queueName;
} /**
* 发送消息
* @param message 消息内容
*/
public void sendMessage(String message){
//获取当前时间戳
long timestamp = System.currentTimeMillis();
//将消息添加到有序集合中
jedis.zadd(queueName, timestamp, message);
} /**
* 接收消息
* @param count 一次接收的消息数量
* @return 返回接收到的消息
*/
public String[] receiveMessage(int count){
//设置最大轮询时间
long timeout = 5000;
//获取当前时间戳
long start = System.currentTimeMillis(); while (true) {
//获取可用的消息数量
long size = jedis.zcount(queueName, "-inf", "+inf");
if (size == 0) {
//如果无消息,休眠50ms后继续轮询
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
//计算需要获取的消息数量count与当前可用的消息数量size的最小值
count = (int) Math.min(count, size);
//获取消息
Set<String> messages = jedis.zrange(queueName, 0, count - 1);
String[] results = messages.toArray(new String[0]);
//移除已处理的消息
jedis.zremrangeByRank(queueName, 0, count - 1);
return results;
} //检查是否超时
if (System.currentTimeMillis() - start > timeout) {
return null; //超时返回空
}
}
} /**
* 销毁队列
*/
public void destroy(){
jedis.del(queueName);
jedis.close();
}
}
使用示例:
public static void main(String[] args) {
//创建消息队列
RedisMessageQueue messageQueue = new RedisMessageQueue("localhost", 6379, "password", "my_queue");
//生产者发送消息
messageQueue.sendMessage("message1");
messageQueue.sendMessage("message2");
//消费者接收消息
String[] messages = messageQueue.receiveMessage(10);
System.out.println(Arrays.toString(messages)); //输出:[message1, message2]
//销毁队列
messageQueue.destroy();
}
在实际应用中,可以结合线程池或者消息监听器等方式,将消息接收过程放置于独立的线程中,以提高消息队列的处理效率。
4.+inf与-inf
+inf 是 Redis 中用于表示正无穷大的一种特殊值,也就是无限大。在使用 Redis 的 zset 集合时,+inf 通常用作 ZREVRANGEBYSCORE 命令的上限值,表示查找 zset 集合中最大的分数值。+inf 后面的 -inf 表示 zset 中最小的分数值。这两个值一起可以用来获取 zset 集合中的所有元素或一个特定范围内的元素。例如:
# 获取 zset 集合中所有元素
ZREVRANGE queue +inf -inf WITHSCORES # 获取 zset 集合中第1到第10个元素(分数从大到小排列)
ZREVRANGE queue +inf -inf WITHSCORES LIMIT 0 9 # 获取 zset 集合中分数在 1581095012 到当前时间之间的元素
ZREVRANGEBYSCORE queue +inf 1581095012 WITHSCORES
在这些命令中,+inf 代表了一个最大的分数值,-inf 代表了一个最小的分数值,用于确定查询的分数值范围。
5.redis使用list与zset做消息队列有什么区别
Redis 使用 List 和 ZSET 都可以实现消息队列,但是二者有以下不同之处:
数据结构不同:List 是一个有序的字符串列表,ZSET 则是一个有序集合,它们的底层实现机制不同。
存储方式不同:List 只能存储字符串类型的数据,而 ZSET 则可以存储带有权重的元素,即除了元素值外,还可以为每个元素指定一个分数。
功能不同: List 操作在元素添加、删除等方面比较方便,而 ZSET 在处理数据排序和范围查找等方面比 List 更加高效。
应用场景不同: 对于需要精细控制排序和分值的场景可以选用 ZSET,而对于只需要简单的队列操作,例如先进先出,可以直接采用 List。
综上所述,List 和 ZSET 都可以用于消息队列的实现,但如果需要更好的性能和更高级的排序功能,建议使用 ZSET。而如果只需要简单的队列操作,则 List 更加适合。
Redis使用ZSET实现消息队列使用总结一的更多相关文章
- (七)整合 Redis集群 ,实现消息队列场景
整合 Redis集群 ,实现消息队列场景 1.Redis集群简介 1.1 RedisCluster概念 2.SpringBoot整合Redis集群 2.1 核心依赖 2.2 核心配置 2.3 参数渲染 ...
- Redis学习笔记~实现消息队列比MSMQ更方便
什么是队列:简单的说就是数据存储到一个空间里(可以是内存,也可以是物理文件),先存储的数据对象,先被取出来,这与堆栈正好相反,消息队列也是这样,将可能出现高并发的数据进行队列存储,并按着入队的顺序依次 ...
- Redis实现简单的消息队列
1.问:什么是消息队列? 答:是一个消息的链表,是一个异步处理的数据处理引擎. 2.问:有什么好处? 答:不仅能够提高系统的负荷,还能够改善因网络阻塞导致的数据缺失. 3.问:用途有哪些? 答:邮件 ...
- redis分布式锁和消息队列
最近博主在看redis的时候发现了两种redis使用方式,与之前redis作为缓存不同,利用的是redis可设置key的有效时间和redis的BRPOP命令. 分布式锁 由于目前一些编程语言,如PHP ...
- Redis与RabbitMQ作为消息队列的比较
简要介绍 RabbitMQ RabbitMQ是实现AMQP(高级消息队列协议)的消息中间件的一种,最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性.扩展性.高可用性等方面表现不俗.消息中间 ...
- RabbitMQ,Apache的ActiveMQ,阿里RocketMQ,Kafka,ZeroMQ,MetaMQ,Redis也可实现消息队列,RabbitMQ的应用场景以及基本原理介绍,RabbitMQ基础知识详解,RabbitMQ布曙
消息队列及常见消息队列介绍 2017-10-10 09:35操作系统/客户端/人脸识别 一.消息队列(MQ)概述 消息队列(Message Queue),是分布式系统中重要的组件,其通用的使用场景可以 ...
- SpringBoot2.0 整合 Redis集群 ,实现消息队列场景
本文源码:GitHub·点这里 || GitEE·点这里 一.Redis集群简介 1.RedisCluster概念 Redis的分布式解决方案,在3.0版本后推出的方案,有效地解决了Redis分布式的 ...
- 使用Redis Stream来做消息队列和在Asp.Net Core中的实现
写在前面 我一直以来使用redis的时候,很多低烈度需求(并发要求不是很高)需要用到消息队列的时候,在项目本身已经使用了Redis的情况下都想直接用Redis来做消息队列,而不想引入新的服务,kafk ...
- redis实现有序的消息队列
redis是什么东西就不多说了,网上文章一搜一大堆. 首先来说一下我要实现的功能: 类似一个消息中转站吧,如果有人要发送消息,先将消息发到我这里来,然后我这边进行转发,为的就是有一个统一的管理和修改时 ...
- redis实现消息队列&发布/订阅模式使用
在项目中用到了redis作为缓存,再学习了ActiveMq之后想着用redis实现简单的消息队列,下面做记录. Redis的列表类型键可以用来实现队列,并且支持阻塞式读取,可以很容易的实现一个高性 ...
随机推荐
- 使用端口排查解决启动Tomcat端口被占问题
有时候在eclipse中启动Tomcat或启动纯净版的Tomcat会出现端口被占的问题,下面菜鸟小编带大家进行端口排查解决问题.(下面假设是我的80端口被占了,如果你不知道你的Tomcat端口是多少就 ...
- SQL-运算
dual表可以进行运算select * from dual; 算数运算 + - * /select 5 + 6 as aaa ,6 - 3 as bbb ,5 * 7 as ccc ,9/2 as d ...
- 20192305 王梓全Python程序设计实验二报告
20192305 王梓全Python程序设计实验二报告 课程:<Python程序设计> 班级: 1923 姓名: 王梓全 学号:20192305 实验教师:王志强 实验日期:2021年4月 ...
- 项目实训DAY6
今天主要的工作是把功能界面丰富了一下,查阅了一下论文,将页面中添加了可视化元素:同时决定了最后几天的工作计划.
- #科技 #资讯 #生活 微信测试更多图片打开方式,神州圆满发射,英伟达或停产性价比神卡,SAMSUNG新一代显存带宽容量双翻倍,这就是今天的其它大新闻
今天是2022年12月01日 十一月初八 现在是中午12:10 下面是今天的其他大新闻 #NEWS 1 # 微信测试用不同小程序打开图片:快捷调用小程序打开图片.视频.文件 ( 新浪科技 ) 据悉,微 ...
- Latex Algorithm 语法错误导致无法编译
遇到了几种情况: 1. for 循环没加{} 2. $\textbf{T_i}$, 想要加粗T,但是把i也扩进去了,latex就不懂了,于是一直recompile不出来说超时什么什么的,把i放到外面就 ...
- 人森第一个iOS app,写给我家baby的!纪念一下
用python写的,对于非专业iOS开发来说,py是个不错的选择,使用beeware框架,感觉和写前端差不多
- 如何服务好B端客户
核心价值: 2B公司的核心价值在于服务.如何服务好客户,需要的是了解客户,与客户共赢. 一.客户信任度的建立 服务:不是口头说说,是要落地与实践. 对于客户的承诺至关重要,承诺的时间点.承诺的事情要保 ...
- 冲刺总结-day7
完成任务:前端设计 设计系统前端,利用html和css对登录页面和进入系统操作界面进行界面化设计,使系统看起来美观.简洁. 一.设计思路 利用HTML对整个网页页面进行布局和设计内容,使用CSS对每一 ...
- Linux系统环境下部署jar程序实现后台运行1
[ nohup java -jar xxx.jar --spring.profiles.active=prod > 日志文件名 2>&1 & ]