redis高级数据结构Stream

文章目录

  • 背景
  • stream概述
    • 消息 ID
    • 消息内容
    • 常见操作
    • 独立消费
    • 创建消费组
    • 消费
  • Stream弊端
    • Stream 消息太多怎么办?
    • 消息如果忘记 ACK 会怎样?
    • PEL 如何避免消息丢失?
    • 分区 Partition
  • Stream 的高可用
  • 总结

背景

为了解决list作为消息队列是无法支持消息多播问题,Redis5.0 多出了一个数据结构 Stream,它是一个新的强大的支持多播的可持久化的消息队列,作者坦言 Redis Stream 狠狠地借鉴了 Kafka 的设计。

stream概述

在这里插入图片描述

Redis Stream 的结构如上图所示,它有一个消息链表,将所有加入的消息都串起来,每个消息都有一个唯一的 ID 和对应的内容。消息是持久化的, Redis 重启后,内容还在。

每个 Stream 都有唯一的名称,它就是 Redis 的 key,在我们首次使用 xadd 指令追加消息时自动创建。

每个 Stream 都可以挂多个消费组,每个消费组会有个游标 last_delivered_id 在 Stream数组之上往前移动,表示当前消费组已经消费到哪条消息了。每个消费组都有一个 Stream内唯一的名称,消费组不会自动创建,它需要单独的指令 xgroup create 进行创建,需要指定从 Stream 的某个消息 ID 开始消费,这个 ID 用来初始化 last_delivered_id 变量。

每个消费组 (Consumer Group) 的状态都是独立的,相互不受影响。也就是说同一份Stream 内部的消息会被每个消费组都消费到。

同一个消费组 (Consumer Group) 可以挂接多个消费者 (Consumer),这些消费者之间是竞争关系,任意一个消费者读取了消息都会使游标 last_delivered_id 往前移动。每个消费者有一个组内唯一名称。

消费者 (Consumer) 内部会有个状态变量 pending_ids,它记录了当前已经被客户端读取的消息,但是还没有 ack。如果客户端没有 ack,这个变量里面的消息 ID 会越来越多,一旦某个消息被 ack,它就开始减少。这个 pending_ids 变量在 Redis 官方被称之为 PEL,也就是 Pending Entries List,这是一个很核心的数据结构,它用来确保客户端至少消费了消息一次,而不会在网络传输的中途丢失了没处理。

消息 ID

消息 ID 的形式是 timestampInMillis-sequence,例如 1527846880572-5,它表示当前的消息在毫米时间戳 1527846880572 时产生,并且是该毫秒内产生的第 5 条消息。消息 ID 可以由服务器自动生成,也可以由客户端自己指定,但是形式必须是整数-整数,而且必须是后面加入的消息的 ID 要大于前面的消息 ID。

消息内容

消息内容就是键值对,形如 hash 结构的键值对,这没什么特别之处。

常见操作

  • 1、 xadd 追加消息
  • 2、 xdel 删除消息,这里的删除仅仅是设置了标志位,不影响消息总长度
  • 3、 xrange 获取消息列表,会自动过滤已经删除的消息
  • 4、 xlen 消息长度
  • 5、 del 删除 Stream

独立消费

我们可以在不定义消费组的情况下进行 Stream 消息的独立消费,当 Stream 没有新消
息时,甚至可以阻塞等待。 Redis 设计了一个单独的消费指令 xread,可以将 Stream 当成普通的消息队列 (list) 来使用。使用 xread 时,我们可以完全忽略消费组 (Consumer Group)的存在,就好比 Stream 就是一个普通的列表 (list)。

客户端如果想要使用 xread 进行顺序消费,一定要记住当前消费到哪里了,也就是返回的消息 ID。下次继续调用 xread 时,将上次返回的最后一个消息 ID 作为参数传递进去,就可以继续消费后续的消息。block 0 表示永远阻塞,直到消息到来, block 1000 表示阻塞 1s,如果 1s 内没有任何消息到来,就返回 nil。类似kafka广播消费,客户端保存offset。

创建消费组

在这里插入图片描述
Stream 通过 xgroup create 指令创建消费组 (Consumer Group),需要传递起始消息 ID 参数用来初始化 last_delivered_id 变量。其实就是kafka广播消费下客户端自己保存offset,消费者在消费前传递offset告知kafka从哪开始消费,果然是借鉴kafka,但是没做到kafka的层度(kafka客户端会自己保存在内存中,不需要使用者自己保存)。

消费

Stream 提供了 xreadgroup 指令可以进行消费组的组内消费,需要提供消费组名称、消费者名称和起始消息 ID。它同 xread 一样,也可以阻塞等待新消息。读到新消息后,对应的消息 ID 就会进入消费者的 PEL(正在处理的消息) 结构里,客户端处理完毕后使用 xack指令通知服务器,本条消息已经处理完毕,该消息 ID 就会从 PEL 中移除。

Stream弊端

Stream 消息太多怎么办?

读者很容易想到,要是消息积累太多, Stream 的链表岂不是很长,内容会不会爆掉?xdel指令又不会删除消息,它只是给消息做了个标志位。

Redis 自然考虑到了这一点,所以它提供了一个定长 Stream 功能。在 xadd 的指令提供一个定长长度 maxlen,就可以将老的消息干掉,确保最多不超过指定长度。

这个类似kafka的日志删除,只是这里固定为根据大小删除,当达到一定量就删除旧数据。

消息如果忘记 ACK 会怎样?

Stream 在每个消费者结构中保存了正在处理中的消息 ID 列表 PEL,如果消费者收到
了消息处理完了但是没有回复 ack,就会导致 PEL 列表不断增长,如果有很多消费组的话,那么这个 PEL 占用的内存就会放大。

PEL 如何避免消息丢失?

在客户端消费者读取 Stream 消息时, Redis 服务器将消息回复给客户端的过程中,客户端突然断开了连接,消息就丢失了。但是 PEL 里已经保存了发出去的消息 ID。待客户端重新连上之后,可以再次收到 PEL 中的消息 ID 列表。不过此时 xreadgroup 的起始消息ID 不能比PEL内的大,而必须是任意有效的消息 ID,一般将参数设为 0-0,表示读取所有的PEL 消息以及自 last_delivered_id 之后的新消息。这其实就像kafka提供seek方法用于客户端指定从哪个offset开始消费。

分区 Partition

Redis 的服务器没有原生支持分区能力,如果想要使用分区,那就需要分配多个Stream,然后在客户端使用一定的策略来生产消息到不同的 Stream。所以个人认为还是kafka强大,stream只是个对kafka进行大量阉割的消息队列,使用上请谨慎。

Stream 的高可用

Stream 的高可用是建立主从复制基础上的,它和其它数据结构的复制机制没有区别,也就是说在 Sentinel 和 Cluster 集群环境下 Stream 是可以支持高可用的。不过鉴于 Redis 的指令复制是异步的,在 failover 发生时, Redis 可能会丢失极小部分数据,这点 Redis 的其它数据结构也是一样的。

总结

如果真需要使用消息队列那么还是选择市面上大家认可的消息队列,以防在后期迭代时发现大量功能问题和性能问题。

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

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

相关文章

ASP.NET Core WebSocket、SignalR

目录 WebSocket SignalR SignalR的基本使用 WebSocket WebSocket基于TCP协议,支持二进制通信,双工通信。性能和并发能力更强。WebSocket独立于HTTP协议,不过我们一般仍然把WebSocket服务器端部署到Web服务器上,因为可以借助HT…

多路文件IO

一、思维导图

在CT107D单片机综合训练平台上,8个数码管分别单独依次显示0~9的值,然后所有数码管一起同时显示0~F的值,如此往复。

题目:在CT107D单片机综合训练平台上,8个数码管分别单独依次显示0~9的值,然后所有数码管一起同时显示0~F的值,如此往复。 延时函数分析LED首先实现8个数码管单独依次显示0~9的数字所有数码管一起同时显示0~F的值,如此往…

小红书提出新面部视频交换方法DynamicFace,可生成高质量且一致的视频面部图像。

DynamicFace是一种新颖的面部视频交换方法,旨在生成高质量且一致的视频面部图像。该方法结合了扩散模型的强大能力和可插拔的时间层,以解决传统面部交换技术面临的两个主要挑战:在保持源面部身份的同时,准确传递目标面部的运动信息…

2025.2.9机器学习笔记:PINN文献阅读

2025.2.9周报 文献阅读题目信息摘要Abstract创新点网络架构实验结论缺点以及后续展望 文献阅读 题目信息 题目: GPT-PINN:Generative Pre-Trained Physics-Informed Neural Networks toward non-intrusive Meta-learning of parametric PDEs期刊: Fini…

天津三石峰科技——汽车生产厂的设备振动检测项目案例

汽车产线有很多传动设备需要长期在线运行,会出现老化、疲劳、磨损等 问题,为了避免意外停机造成损失,需要加装一些健康监测设备,监测设备运 行状态。天津三石峰科技采用 12 通道振动信号采集卡(下图 1)对…

CSGHub高效管理|解锁DeepSeek R1蒸馏模型 :高效推理的新选择

在大模型的新时代,如何在保持高推理能力的同时降低计算成本,已经成为企业和开发者们关注的核心问题。 你是否也在寻找一个既强大又高效的AI模型? DeepSeek R1,作为目前领先的AI模型之一,不仅推出了强大的671B参数旗舰模…

来自国外的实用软件 ,已接触所有限制!

今天我给大家带来了一款超棒的全自动抠图软件,真的是一个来自国外的宝藏工具!而且好消息是,它现在完全解除了限制,可以无限畅快地使用了。 Teorex PhotoScissors 抠图软件 这款软件特别贴心,根本不需要安装&#xff0…

win32汇编环境,结构体的使用示例一

;运行效果 ;win32汇编环境,结构体的使用示例一 ;举例说明结构体的定义,如何访问其中的成员,使用assume指令指向某个结构体,利用偏移得到成员值等 ;直接抄进RadAsm可编译运行。重要部分加备注。 ;下面为asm文件 ;>>>>>>>…

Ai无限免费生成高质量ppt教程(deepseek+kimi)

第一步:打开deepseek官网(DeepSeek) 1.如果deepseek官网网络繁忙,解决方案如下: (1)使用easychat官网(EasyChat)使用deepseek模型,如图所示: (2)本地部署&…

C#常用集合优缺点对比

先上结论&#xff1a; 在C#中&#xff0c;链表、一维数组、字典、List<T>和ArrayList是常见的数据集合类型&#xff0c;它们各有优缺点&#xff0c;适用于不同的场景。以下是它们的比较&#xff1a; 1. 一维数组 (T[]) 优点&#xff1a; 性能高&#xff1a;数组在内存中…

大数据项目2a:基于spark的电影推荐和分析系统设计与实现

1、项目目的 本项目的目的是设计并实现一个基于Spark的电影推荐系统&#xff0c;以应对大数据环境下电影推荐服务的挑战。通过整合电影、评分和用户数据集&#xff0c;并利用SparkSql框架进行高效处理&#xff0c;系统能够为用户提供个性化的电影推荐。项目采用多种先进技术&…

CANoe工具使用技巧 --- 如何使用 “on ethernetPacket “事件处理程序

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 简单,单纯,喜欢独处,独来独往,不易合同频过着接地气的生活,除了生存温饱问题之外,没有什么过多的欲望,表面看起来很高冷,内心热情,如果你身…

数据库5(MySQL版)

作业要求 触发器 mysql> create trigger after_order_insert -> after insert on orders -> for each row -> update goods set num num - new.onum where gid new.gid; mysql> create trigger after_order_delete -> after delete on or…

【异常解决】在idea中提示 hutool 提示 HttpResponse used withoud try-with-resources statement

博主介绍&#xff1a;✌全网粉丝22W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…

浅析Ruby类污染及其在Sinatra框架下的利用

和JavaScript中的原型链污染类似&#xff0c;Ruby中也存在类似的概念——类污染&#xff0c;两者都是对象进行不安全的递归合并导致的。 网上也没有相关的分析文章&#xff0c;只有下面这篇文章应该是第一次谈到这个问题 Class Pollution in Ruby: A Deep Dive into Exploiti…

SamWaf开源轻量级的网站应用防火墙(安装包),私有化部署,加密本地存储的数据,易于启动,并支持 Linux 和 Windows 64 位和 Arm64

一、SamWaf轻量级开源防火墙介绍 &#xff08;文末提供下载&#xff09; SamWaf网站防火墙是一款适用于小公司、工作室和个人网站的开源轻量级网站防火墙&#xff0c;完全私有化部署&#xff0c;数据加密且仅保存本地&#xff0c;一键启动&#xff0c;支持Linux&#xff0c;Wi…

14vue3实战-----获取用户信息和用户的菜单树信息

14vue3实战-----获取用户信息和用户的菜单树信息 1.获取用户信息1.1封装接口1.2优化 2.获取用户的菜单树信息 1.获取用户信息 1.1封装接口 后端有根据id获取用户信息的接口&#xff0c;前端需要把该接口封装一下: service/login/login.ts&#xff1a; import hyRequest from…

洛谷算法1-3 暴力枚举

目录 1 P2241统计方形 2 三连击 3 选数 4 P1088 [NOIP2004 普及组] 火星人 5 P3799 小 Y 拼木棒 排列组合 6 P2392 kkksc03考前临时抱佛脚 7 P2036 [COCI2008-2009 #2] PERKET 1 P2241统计方形 思路&#xff1a; 本题中&#xff0c;矩阵数量正方形数量长方形数量&#xff0…

CSS Overflow 属性详解:控制内容溢出的利器

在前端开发中&#xff0c;处理内容溢出是一个常见的需求。CSS 提供了 overflow 属性&#xff0c;帮助我们控制当内容超出元素框时的显示方式。本文将详细介绍 overflow 属性的各种取值及其应用场景。 1. 什么是 overflow 属性&#xff1f; overflow 属性用于控制当元素的内容…