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

redis实现消息队列

背景

消息队列(Message Queue)是一种常见的软件架构模式,用于在分布式系统中传递和处理异步消息。它解耦了发送消息的应用程序和接收消息的应用程序之间的直接依赖关系,使得消息的发送者和接收者可以独立地演化和扩展。

消息队列的基本原理是发送者将消息发送到一个中间代理(即消息队列),然后接收者从该中间代理中消费消息。中间代理充当了消息的缓冲区,确保消息的可靠传递和持久化存储(根据需要),同时提供了高吞吐量、低延迟和可伸缩性。

消息队列的原理图

相信在做分布式服务开发的时候,或多或少的使用到了消息队列,如主流的kafkarocketMQ。总结下来,消息队列的优点包括:

  • 异步通信:发送者和接收者之间的解耦,使得它们可以独立地操作和演化,无需实时等待回应。
  • 应用解耦:消息队列使不同的应用程序能够以独立的方式进行开发、部署和伸缩,降低了系统之间的耦合度。
  • 削峰填谷:消息队列可以作为缓冲区,处理突发的请求和高峰期的流量,从而减轻系统的压力。
  • 消息持久化:消息队列可以将消息持久化存储,确保在异常情况下不会丢失消息。
  • 可靠性和扩展性:消息队列提供了高可靠性和可伸缩性,通过多个消费者处理大量的消息。

总而言之,消息队列是一种强大的软件架构模式,通过解耦应用程序之间的依赖关系,提供了高可靠性、高吞吐量和可伸缩性的消息传递机制。它在构建分布式系统、处理异步任务和解决系统耦合等方面发挥着重要作用。

那今天的案例呢,没有使用到kafka rocketMQ, 而是继续我的专题redis

redis实现消息队列

list

list这种数据结构天然的支持消息队列,常用的命令如下:

命令描述
LPUSH key value在列表头部插入一个或多个值
RPUSH key value在列表尾部插入一个或多个值
LPOP key弹出并返回列表头部的一个值
RPOP key弹出并返回列表尾部的一个值
LRANGE key start stop获取列表中指定范围内的所有值
LLEN key获取列表的长度

list实现消息队列的常用命令案例

好的,这个shigen用Java的代码实现以下:

  • 创建消息队列服务类redisMessageQueueService

主要的是三个方法,发送数据、消费数据和判断消息队列是否为空。

  • 消息处理类messProcessor

这个类或者说是组件主要是处理消息,这里简单的在控制台输出打印。

  • 系统的接口messageQueueController

其实就是通过接口的方式调用messageQueueServie,实现消息的发送和接受消费。

那最终的效果是什么样的呢》我本地使用的是curl进行的进一步的测试。

list实现的方式测试效果:

list实现的方式测试效果

最后,总结一下list实现消息队列的优缺点:

优点:

  • 简单易用:Redis的List数据结构操作简单,易于理解和使用。
  • 支持多样化操作:List数据结构提供了丰富的操作方法,如插入、删除、获取范围等。

缺点:

消息队列的设计最重要的就是消息的防丢失问题

  • 缺乏消息确认机制:List方式没有内置的消息确认机制,当消费者处理消息失败或发生异常时,消息可能会丢失。
  • 不支持消息持久化:Redis的List数据结构默认存储在内存中,当Redis重启或宕机时,消息也会丢失。
  • 不适合高并发场景:在高并发情况下,List方式可能存在性能问题,因为LPUSH和BRPOP是单线程操作,无法充分利用多核CPU的优势。
  • 不适合多订阅者。现在的list是一对一的模式,不支持一对多的模式。

pub/sub模式

针对list一对一的模式,pub/sub可以实现一对多的模式。

常见的redis操作命令如下:

命令描述
PUBLISH channel message将消息 message 发送到指定的频道 channel
SUBSCRIBE channel [channel …]订阅一个或多个频道,接收这些频道中发布的消息
UNSUBSCRIBE [channel [channel …]]取消订阅一个或多个频道
PSUBSCRIBE pattern [pattern …]订阅一个或多个符合给定模式的频道
PUNSUBSCRIBE [pattern [pattern …]]取消订阅一个或多个符合给定模式的频道
PUBSUB subcommand [argument [argument …]]获取关于 Redis Pub/Sub 状态的信息

我们在控制台测试一下:

那具体的代码如何实现呢?这里依旧选取的是Java代码作为案例的设计。

  • 定义消息发布的接口并实现发送消息的操作MessagePublisherImpl

  • 消息订阅者messageSubscriberImpl

  • 配置类中加上redisMessageListenerContainer的bean

  • controller测试

服务运行,接口测试一下:

订阅多个topic的话,这样设置:

container.addMessageListener(messageListener, new PatternTopic("pub_channel"));
// 监听多个topic
container.addMessageListener(messageListener, new PatternTopic("pub_channel1"));

ok,貌似这种方式也显得很nice,至少比list的实现方式更nice,那它能解决实际的问题吗?我们总结一下这种方式的优缺点:

优点:

  • 实现了多个消费者订阅同一个topic

缺点

  • 数据不可靠:Redis 的 pub/sub 模式没有任何持久化机制,如果发布的消息在订阅者还没有收到前发生宕机,那么这些消息将会丢失。因此,如果需要确保数据的可靠性和持久化,需要使用 Redis 的其他数据结构或者使用 Redis 的 AOF 或 RDB 持久化机制。

  • 消息不能防止重复消费:Redis 的 pub/sub 模式不支持消息的确认和回调机制,因此,当订阅者收到消息时,无法对其进行确认,也就无法防止重复消费

那有什么好的解决方式呢?stream应需求而生。

stream

Redis 的 Stream 是一个基于时间序列的数据结构,用于存储和处理消息。Stream 可以看作是一个由消息组成的日志,每个消息都有一个唯一的 ID(可以是时间戳或其他方式生成),并且可以对消息进行按照时间的顺序和优先级进行排序。

Stream 可以支持多个消费者,并且可以保证每个消费者只能消费一次。Stream 还可以在一个组内进行消费者间负载均衡,以提高系统的可扩展性和高可用性。

常用的API如下:

API描述
XADD向指定的 Stream 中添加一个条目(消息)XADD key ID field string [field string …]
XDEL从指定的 Stream 中删除一个或多个条目
XRANGE获取指定范围内的条目
XREVRANGE获取指定范围内的逆序条目
XLEN获取 Stream 中的条目数量
XREAD从一个或多个 Stream 中读取待处理的条目
XGROUP创建、管理和操作消费者组
XACK确认一个或多个已处理的条目
XCLAIM批量方式对待处理的条目进行声明和处理
XPENDING获取待处理的条目信息
XTRIM删除指定范围之外的条目
XINFO获取 Stream 的相关信息

参考文章:基于Redis的Stream类型的完美消息队列解决方案

添加和读取消息的命令测试如下:

shigen在敲命令的时候也觉得很繁琐,有点麻烦,还是期待Java代码的api去操作消息队列。

参考文章:redis灵魂拷问:如何使用stream实现消息队列 如何在Springboot中使用Redis5的Stream

  • 定义生产消息的messageProcuder

主要是用来实现消息的发送

  • 消息的接受messageReceiver

实现了消息的ack

  • 测试接口

测试中发现了如下错误:

使用stream并不适合用jedis作为连接池。因为我之前的案例都是基于jedis的,在这里果断的放弃了。

好了,以上就是《redis实现消息队列》的全部内容了。


shigen一起,每天不一样!

相关文章:

redis实现消息队列

背景 消息队列(Message Queue)是一种常见的软件架构模式,用于在分布式系统中传递和处理异步消息。它解耦了发送消息的应用程序和接收消息的应用程序之间的直接依赖关系,使得消息的发送者和接收者可以独立地演化和扩展。 消息队列…...

JVM指令集

概述 JVM,Java Virtual Machine,Java虚拟机器,作为一台独立的机器,一般包括独立的指令集、独立的存储体系以及适合机器自身的运算方式,本章节主要是描述JVM指令的功能与作用。 JVM的每个指令的格式是【指令 操作数1操…...

如何用SSH克隆GitHub项目

诸神缄默不语-个人CSDN博文目录 使用场景:由于不可知的网络问题,无法用HTTPS克隆GitHub项目。 报错fatal: unable to access https://github.com/PolarisRisingWar/llm-throught-ages.git/: GnuTLS recv error (-110): The TLS connection was non-pro…...

sqlx库使用指南

sqlx库使用指南 在项目中我们通常可能会使用database/sql连接MySQL数据库。本文借助使用sqlx实现批量插入数据的例子,介绍了sqlx中可能被你忽视了的sqlx.In和DB.NamedExec方法。 sqlx介绍 在项目中我们通常可能会使用database/sql连接MySQL数据库。sqlx可以认为是Go…...

算法篇汇总

文章浏览 I https://leetcode.cn/problems/article-views-i/description/?envTypestudy-plan-v2&envId30-days-of-pandas&langpythondata 我的题解: import pandas as pddef article_views(views: pd.DataFrame) -> pd.DataFrame:dfviews[views[auth…...

typeScript 学习笔记(二)

类接口 TypeScript 入门教程 (xcatliu.com) 十四.类 ① 类 类:定义了一件事物的抽象特点,包含它的属性和方法对象:类的实例,通过new生成面向对象(OOP)的三大特性:封装、继承、多态封装&…...

redis集群架构详解

一、集群架构搭建 1、配置 在一台机器上模拟多台机器搭建redis集群,一个集群代表一台物理机 集群1路径: /usr/local/redis/redis-cluster/cluster1/9001/redis.conf/usr/local/redis/redis-cluster/cluster1/9004/redis.conf/usr/local/redis/redis-…...

nodejs设置镜像

1、npm镜像地址配置 -- 查看 npm 安装目录 npm root -g-- 查看 npm 配置信息 npm config list-- 查询当前镜像配置 npm get registry-- 或者仅修改 npm 命令镜像 -- 设置为淘宝镜像 npm config set registry https://registry.npmmirror.com -- 修改为官方镜像 npm config set…...

CSS中如何在table中隐藏表格中从第4个开始的多个 <tr> 元素

隐藏指定行 使用 CSS 的 nth-child 选择器来选择表格中的特定行,并隐藏它们。 以下是一个示例 CSS 规则,用于隐藏表格中的第 4 个和第 5 个行(索引从 1 开始): table tr:nth-child(4), table tr:nth-child(5) {displ…...

【类和对象】③友元类

文章目录 1.初始化列表2.static静态成员3.友元 1.初始化列表 我们知道在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值。虽然调用构造函数之后,对象中已经有了一个初始值,但是不能将其称为对对象中成…...

算法通关村第十六关:黄金挑战:滑动窗口与堆结合

黄金挑战:滑动窗口与堆结合 堆的大小一般是有限的,能直接返回当前位置下的最大值或者最小值 该特征与滑动窗口结合,可以解决一些特定场景的问题 1. 滑动窗口与堆问题的结合 LeetCode239 https://leetcode.cn/problems/sliding-window-maxi…...

6.2.2 【MySQL】InnoDB中的索引方案

上边之所以称为一个简易的索引方案,是因为我们为了在根据主键值进行查找时使用二分法快速定位具体的目录项而假设所有目录项都可以在物理存储器上连续存储,但是这样做有几个问题: InnoDB 是使用页来作为管理存储空间的基本单位,也…...

划片机实现装片、对准、切割、清洗到卸片的自动化操作

划片机是一种用于切割和分离材料的设备,通常用于光学和医疗、IC、QFN、DFN、半导体集成电路、GPP/LED氮化镓等芯片分立器件、LED封装、光通讯器件、声表器件、MEMS等行业。划片机可以实现从装片、对准、切割、清洗到卸片的自动化操作。 以下是划片机实现这些操作的步…...

OpenCV(二十五):边缘检测(一)

目录 1.边缘检测原理 2.Sobel算子边缘检测 3.Scharr算子边缘检测 4.两种算子的生成getDerivKernels() 1.边缘检测原理 其原理是基于图像中灰度值的变化来捕捉图像中的边界和轮廓。梯度则表示了图像中像素强度变化的强弱和方向。 所以沿梯度方向找到有最大梯度值的像素&…...

上行取消指示 DCI format 2_4

上篇介绍了DCI format 2_1的DL传输中断的内容,这篇就看下DCI format 2_4有关的UL 传输取消机制,值得注意的是这里的UL传输针对的是PUSCH和SRS传输。 UL cancellation DCI format 2_4相关机制引入的背景与DCI format 2_1一样,都是因为URLLC和e…...

百望云蝉联2023「Cloud 100 China 」榜单 综合实力再获认可

9月7日,2023 Cloud 100 China 榜单于上海中心正式发布,榜单由靖亚资本与崔牛会联合推出,百望云凭借着过硬的综合实力与卓越的技术创新能力,再次荣登榜单,位居第六位。 本届评选,Top 100 企业的数据指标的权…...

力扣刷题班第1节:Python语法常遗漏的知识

以下仅仅记录和后面力扣刷题相关的、且平常会遗漏的语法知识。 下面这些笔记都是点到为止,不进行深入解释。大多数学过python的朋友看到就知道什么意思的,我就不解释了 字符串 str "I am a cook"# 按照空格切分 str.split(" ") …...

GET 和 POST请求的区别是什么

GET和POST是HTTP请求的两种基本方法,要说它们的区别,接触过WEB开发的人都能说出一二。 最直观的区别就是GET把参数包含在URL中,POST通过request body传递参数。 你轻轻松松的给出了一个“标准答案”: GET在浏览器回退时是无害的…...

Python数据分析实战-表连接-merge四种连接方式用法(附源码和实现效果)

实现功能 表连接-merge四种连接方式用法, 将两个pandas表根据一个或者多个键(列)值进行连接。 实现代码 import pandas as pddf1 pd.DataFrame({key: [a, b, d],data1: range(3)}) print(df1)df2 pd.DataFrame({key: [a, b, c, a, b],dat…...

NFTScan 浏览器再升级:优质数据服务新体验来袭

当前,高质量的 NFT 数据服务已成为区块链用户和开发者的必需。为满足用户数据需求,NFTScan 主站近日进行全面升级,优化了数据服务板块的页面结构,实现更清晰简洁的布局和交互。 NFTScan 的改版充分考虑用户和开发者的数据体验&am…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

pam_env.so模块配置解析

在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

vulnyx Blogger writeup

信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...

Linux安全加固:从攻防视角构建系统免疫

Linux安全加固:从攻防视角构建系统免疫 构建坚不可摧的数字堡垒 引言:攻防对抗的新纪元 在日益复杂的网络威胁环境中,Linux系统安全已从被动防御转向主动免疫。2023年全球网络安全报告显示,高级持续性威胁(APT)攻击同比增长65%,平均入侵停留时间缩短至48小时。本章将从…...

如何通过git命令查看项目连接的仓库地址?

要通过 Git 命令查看项目连接的仓库地址,您可以使用以下几种方法: 1. 查看所有远程仓库地址 使用 git remote -v 命令,它会显示项目中配置的所有远程仓库及其对应的 URL: git remote -v输出示例: origin https://…...

LangChain【6】之输出解析器:结构化LLM响应的关键工具

文章目录 一 LangChain输出解析器概述1.1 什么是输出解析器?1.2 主要功能与工作原理1.3 常用解析器类型 二 主要输出解析器类型2.1 Pydantic/Json输出解析器2.2 结构化输出解析器2.3 列表解析器2.4 日期解析器2.5 Json输出解析器2.6 xml输出解析器 三 高级使用技巧3…...