Redis 如何实现消息队列?

在当今的分布式系统架构中,消息队列起着至关重要的作用,它能够帮助系统实现异步通信、解耦组件以及缓冲流量等功能。Redis,作为一款高性能的键值对存储数据库,也为我们提供了便捷的方式来构建消息队列。今天,咱们就深入探讨一下 Redis 是如何实现消息队列的。

一、Redis 消息队列的基础

Redis 本身提供了一些基本的数据结构,如列表(List),这为消息队列的实现奠定了基础。列表在 Redis 中是一个有序的字符串链表,我们可以利用它的两端操作特性来模拟消息队列的入队(push)和出队(pop)操作。

例如,使用 LPUSH 命令将消息从队列头部插入,这类似于生产者向队列中投递消息:

 

LPUSH myqueue "message1"

LPUSH myqueue "message2"

而消费者则可以使用 RPOP 命令从队列尾部取出消息,实现消息的消费:

 

RPOP myqueue

不过,这里存在一个小问题。当队列中没有消息时,消费者执行 RPOP 操作会立即返回 nil,这意味着消费者需要不断地轮询队列,这无疑会浪费大量的 CPU 资源。

二、阻塞式读取 - BRPOP 与 BLPOP

为了解决消费者轮询浪费资源的问题,Redis 提供了阻塞式读取命令 BRPOP 和 BLPOP。这两个命令的工作方式类似,以 BRPOP 为例,当队列中没有消息时,消费者执行 BRPOP 命令会进入阻塞状态,直到队列中有新的消息到来,才会立即返回新消息。

 

BRPOP myqueue 0

上述命令中的 “0” 表示阻塞时间,如果设置为一个正数,如 5,表示阻塞 5 秒,如果 5 秒内没有消息,将返回 nil。这种阻塞式读取方式极大地优化了消费者的资源使用效率,使得消费者可以 “安静” 地等待消息,而不是无意义地空转。

三、发布 / 订阅模式(Pub/Sub)

除了基于列表的简单队列实现,Redis 还提供了发布 / 订阅模式,这种模式更适合于广播式的消息传递场景。

在这个模式下,有发布者(Publisher)和订阅者(Subscriber)两种角色。发布者使用 PUBLISH 命令向指定频道(Channel)发送消息:

 

PUBLISH mychannel "important news"

而订阅者则使用 SUBSCRIBE 命令订阅感兴趣的频道:

 

SUBSCRIBE mychannel

一旦发布者向频道发送了消息,所有订阅该频道的订阅者都能即时收到消息。不过,需要注意的是,这种模式下如果订阅者在消息发布时处于离线状态,那么它将会错过这些消息,因为 Redis 的发布 / 订阅模式默认不支持消息持久化。

四、基于 Sorted Set 实现延迟队列

在实际应用中,我们常常会遇到需要延迟处理消息的场景,比如订单下单后 30 分钟未支付则自动取消。Redis 的 Sorted Set 数据结构可以巧妙地实现延迟队列。

我们可以将消息的处理时间戳作为 Sorted Set 的分值(score),消息内容作为成员(member),使用 ZADD 命令添加到 Sorted Set 中:

 

ZADD delayqueue 1677325200 "order1-cancel-task"

这里的 1677325200 是未来某个时间的时间戳。

然后,消费者可以通过定时任务,每隔一段时间(比如 1 秒),使用 ZRANGEBYSCORE 命令查询分值小于当前时间戳的消息,并将它们取出来进行处理:

 

ZRANGEBYSCORE delayqueue 0 1677325200 WITHSCORES LIMIT 0 10

这样就实现了延迟队列的功能,确保消息在合适的时间被处理。

Redis 凭借其丰富的数据结构,为我们提供了多样的消息队列实现方式,无论是简单的异步任务队列,还是复杂的延迟队列、广播式的发布 / 订阅场景,都能找到对应的解决方案。在实际项目中,我们可以根据具体的业务需求,灵活选用合适的 Redis 消息队列实现策略,让系统间的通信更加高效、流畅。

当然,在使用 Redis 消息队列时,也要注意一些问题,比如队列的持久化设置、消息的可靠性保证等,后续我们可以进一步探讨如何优化 Redis 消息队列在生产环境中的应用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/70626.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【多线程-第三天-NSOperation的练习-tableView异步下载网络图片-下载操作缓存池 Objective-C语言】

一、下载操作缓存池 1.下面我们来看操作缓存池,我们先演示一下问题,看看为什么要加这么一个操作缓存池,什么是操作缓存池,不用管呢,我们先来看啊,首先有什么问题, 看这个问题之前,我这儿写一个touch,点击屏幕的时候调用, 额,不能点击屏幕啊,因为现在屏幕点不着,我…

【2025深度学习环境搭建-1】在Win11上用WSL2和Docker解锁GPU加速

建议有: 较新的win11电脑,GPU是nvidia一点点Linux基础一点点Docker基础 一、安装WSL2 【控制面板】》【程序】》【启用或关闭Windows功能】 打开三个功能:【Hyper-V】【Virtual Machine Platform】【适用于Linux的Windows子系统】 可能看…

深入探索 DeepSeek 在数据分析与可视化中的应用

在数据驱动的时代,快速且准确地分析和呈现数据对于企业和个人都至关重要。DeepSeek 作为一款先进的人工智能工具,凭借其强大的数据处理和可视化能力,正在革新数据分析的方式。 1. 数据预处理与清洗 在进行数据分析前,数据预处理…

C#基础:类的三大特性 之 封装

一、封装、继承、多态关系说明 封装、继承、多态这三大特性是相互关联的,封装和继承几乎都是为多态而准备的。 封装是基础,继承是关键,多态性是补充。 多态性存在于继承性之中,它是继承性的进一步扩展,没有继承就没…

vscode无法预览Markdown在线图片链接

问题:在VSCode中,打开MarkDown文件,存在在线图片链接, 但是在预览时却无法显示。 原因:因为Visual Studio Code中的MarkDown默认配置中只允许载入安全内容 解决方法: 1、输入快捷键 Ctrl Shift P 打开…

mongodb的并发优化

MongoDB的锁模式 MongoDB的锁设计 MongoDB的高性能表现离不开它的多粒度锁机制。多粒度主要可以针对不同层级的数据库对象进行枷锁,通过避免全局性的互斥来提升并发能力。从整个数据库层面看,MongoDB的并发锁的分层如下图所示: 从上往下是一…

Python 环境管理介绍

pip pip 是 Python 的标准包管理工具&#xff0c;用于安装和管理 Python 软件包。它允许你从 Python 包索引&#xff08;PyPI&#xff09;下载并安装第三方库&#xff0c;并能自动解决依赖问题。 第三方库的安装与卸载 pip install <package>pip uninstall <packag…

oracle apex post接口

日常记录 使用到了apex_json方式接收 、、、1 首先&#xff0c;接口通过body传递过来&#xff0c;成功接收到&#xff0c; 数据格式为 JSON_OBJECT_T l_json : JSON_OBJECT_T.parse(:body); 这里我用参数接收到 然后 里面是包含了 "data" 我用 继续接收到这个 l…

PLC通讯

PPI通讯 是西门子公司专为s7-200系列plc开发的通讯协议。内置于s7-200 CPU中。PPI协议物理上基于RS-485口&#xff0c;通过屏蔽双绞线就可以实现PPI通讯。PPI协议是一种主-从协议。主站设备发送要求到从站设备&#xff0c;从站设备响应&#xff0c;从站不能主动发出信息。主站…

易飞报错:输入的库位并不存在,请重新输入

首先&#xff0c;判断使用的账套是否启用了库位管理&#xff0c;若启用&#xff0c;检查库位信息是否正确&#xff0c; 若没启用&#xff0c;可以进行一下操作处理&#xff1a; 首先在公用参数中启用库位管理&#xff0c; 然后使用取消库位管理进行取消操作。 以上方法基本可以…

綫性與非綫性泛函分析與應用_3.例題-母本

第3章 巴拿赫空間 1. 巴拿赫不動點定理 例題1 問題:在完備度量空間(\mathbb{R},d)(d(x,y)=\vert x - y\vert)中,定義映射f(x)=\frac{1}{2}x + 1,求f的不動點。 解析:首先驗證f是壓縮映射。對於任意x,y\in\mathbb{R},d(f(x),f(y))=\vert(\frac{1}{2}x + 1)-(\frac{1}{2…

go语言闭包的立即执行和不立即执行

在 Go 语言中&#xff0c;闭包&#xff08;closure&#xff09;是一种特殊的函数&#xff0c;它可以访问其定义时所在的作用域中的变量&#xff0c;即使这个函数在其他地方被调用。闭包的“立即执行”和“不立即执行”主要取决于闭包的定义和调用方式。 1. 闭包的定义 闭包是…

Mybatis常用动态 SQL 相关标签

1. <if> 用于条件判断&#xff0c;当满足条件时执行对应的 SQL 片段。 示例: <select id"findUser" resultType"User">SELECT * FROM usersWHERE 11<if test"name ! null and name ! ">AND name #{name}</if><if…

500字理透react的hook闭包问题

在react中hook的闭包问题很容易在不经意间犯错&#xff0c;项目写大了之后更是难以找到到底是哪里出了问题。 为什么会出现闭包问题 出现闭包问题的原因就是函数中操作的变量不是最新的变量&#xff0c;什么意思呢&#xff0c;我们知道函数组件每次刷新都是重新运行一次函数&…

买股票的最佳时机 - 2

买卖股票的最佳时机 III 题目描述&#xff1a; 提示&#xff1a; 1 < prices.length < 1050 < prices[i] < 105 分析过程&#xff1a; 写动态规划&#xff0c;我们需要考虑一下问题&#xff1a; 定义状态状态转移方程初始条件 遍历顺序 4种状态&#xff1a; …

【HarmonyOS Next】地图使用详解(一)

背景 这系列文章主要讲解鸿蒙地图的使用&#xff0c;当前可以免费使用&#xff0c;并提供了丰富的SDK给开发者去自定义控件开发。目前可以实现个性化显示地图、位置搜索和路径规划等功能&#xff0c;轻松完成地图构建工作。需要注意的是&#xff0c;现在测试只能使用实体手机去…

【C++】 时间库chrono计算程序运行时间

C 时间库chrono计算程序运行时间 本文总结了chrono库的引入方法以及计算程序片段运行时间的方法 一、chrono库的引入方法&#xff08;注意事项&#xff09; 首先chrono是属于std命名空间的。 所以在程序中应该这样包含头文件&#xff1a; #include <chrono> using n…

计算机毕业设计SpringBoot+Vue.jst0甘肃非物质文化网站(源码+LW文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

EVM系区块链开发网节点搭建及测试详细文档

文章目录 一. 编写说明1.1 文档说明1.2 配置信息二. docker 方式部署区块链开发网2.1 centos7 部署docker环境2.1.1 卸载旧版本2.1.2 使用 yum 安装2.1.3 使用官方安装脚本自动安装2.1.4 启动并加入开机启动2.2 区块链节点镜像生成2.3 区块链开发网节点容器生成2.3.1 配置文件编…

第4章 4.1 Entity Framework Core概述

4.1.1 什么是ORM ORM (object tralstional mapping ,对象关系映射)中的“对象”指的就是C#中的对象&#xff0c;而“关系”是关系型数据库&#xff0c;“映射”指搭建数据库与C#对象之间的“桥梁”。 比如使用ORM &#xff0c;可以通过创建C#对象的方式把数据插入数据库而不需…