Redis内存优化——Stream类型介绍及底层原理详解


前言

Redis是一个开源的高性能键值数据库,它支持多种数据结构,如字符串、列表、集合、散列、有序集合等。在Redis 5.0版本中,新增了一种数据结构:Stream,它主要用于实现消息队列(MQ,Message Queue)

消息队列是一种异步通信机制,它允许多个生产者和消费者之间发送和接收消息,而不需要直接相互联系。消息队列有很多优点,如解耦、缓冲、重试、负载均衡、广播等。消息队列也有很多应用场景,如日志收集、任务调度、数据同步、事件驱动等。


Stream

概述

stream 是一个类似于日志的数据结构,它可以记录一系列的键值对,每个键值对都有一个唯一的 ID。一个 stream 类型的键最多可以存储 2^64 - 1 个键值对。

stream 类型的底层实现是 rax(基数树),它是一种压缩的前缀树结构,它将所有的键值对按照 ID 的字典序存储在一个树形结构中。rax 可以快速地定位、插入、删除任意位置的键值对

应用场景

stream 类型的应用场景主要是实现事件驱动的架构,比如:

  • 消息队列,利用 xadd 和 xread 命令实现生产者消费者模式。
  • 操作日志,利用 xadd 和 xrange 命令实现操作记录和回放。
  • 数据同步,利用 xadd 和 xreadgroup 命令实现多个消费者组之间的数据同步。

底层原理

Rax Tree

rax tree是一种基于基数树(radix tree)的变体,也叫做压缩前缀树(compressed prefix tree),它被应用于redis stream中,用来存储streamID,其数据结构为

typedef struct raxNode {
    uint32_t iskey:1;     /* Does this node contain a key? */
    uint32_t isnull:1;    /* Associated value is NULL (don't store it). */
    uint32_t iscompr:1;   /* 前缀是否压缩 */
    uint32_t size:29;     /* Number of children, or compressed string len. */
    unsigned char data[];
} raxNode;
  • iskey:是否包含key
  • isnull:是否存储value值
  • iscompr:前缀是否压缩。决定了size存储的是什么和data的数据结构
  • size
    • iscompr=0:节点为非压缩节点size是孩子节点的数量
    • iscompr=1:节点为压缩节点size是已压缩的字符串长度
  • data
    • iscompr=0:节点为非压缩节点,数据格式为[header strlen=0][abc][a-ptr][b-ptr][c-ptr](value-ptr?)。其有size个字符,
    • iscompr=1:节点为压缩节点,数据格式为[header strlen=3][xyz][z-ptr](value-ptr?)

为了便于理解,设定一些场景举例说明

场景一:只插入foot

数据结构为:
请添加图片描述

其中,z-ptr指向的叶子节点的iskey=1,标识foot这个key。下图为使用树状图的形式来展现其数据结构
请添加图片描述

场景二:插入foot后,插入footer

数据结构为:

请添加图片描述

其插入过程为:

  1. foot节点中每个字符进行比较,获得最大公共前缀foot
  2. er作为foot的子节点,其iskey=1,标识foot这个key
  3. er的子节点的iskey=1,标识footer这个key

下图为使用树状图的形式来展现其数据结构

请添加图片描述

场景三:插入foot后,插入fo

数据结构为:

请添加图片描述

其插入过程为:

  1. foot节点中每个字符进行比较,获得最大公共前缀fo
  2. foot拆成foot
  3. ot作为fo的子节点,其iskey=1,标识fo这个key
  4. 设置ot的子节点的iskey=1,标识foot这个key

下图为使用树状图的形式来展现其数据结构

请添加图片描述

场景四:插入foot后,插入foobar

数据结构为:

请添加图片描述

其插入过程为:

  1. foot节点中每个字符进行比较,获得最大公共前缀foo
  2. foot拆成foot
  3. footbar拆成foobar
  4. tb作为foo的子节点
  5. 设置ot的子节点的iskey=1,标识foot这个key
  6. ar作为b的子节点
  7. 设置ar的子节点的iskey=1,标识footbar这个key

下图为使用树状图的形式来展现其数据结构

请添加图片描述

Stream

stream的底层使用了rax treelistpack两种结构,rax tree用来存储streamID,而listpack用来存储对应的值,结构图如下:

请添加图片描述


总结

本文介绍了Redis Stream的类型介绍及底层原理。Redis Stream是一种非常强大和灵活的数据结构,它不仅可以实现高级消息队列的功能,还可以支持多种模式和场景。Redis Stream是Redis 5.0版本中新增加的数据结构,它体现了Redis作为一个开源项目不断创新和进步的精神。


系列文章目录

Redis内存优化——String类型介绍及底层原理详解
Redis内存优化——Hash类型介绍及底层原理详解
Redis内存优化——List类型介绍及底层原理详解
Redis内存优化——Set类型介绍及底层原理详解
Redis内存优化——ZSet类型介绍及底层原理详解
Redis内存优化——Stream类型介绍及底层原理详解
Redis内存优化——Hyperloglog、GEO、Bitmap、Bitfield类型详解
Redis的三种持久化策略及选取建议

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr___Ray

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值