Redis数据结构SortedSet的底层原理解析

 更新时间:2022年07月13日 15:59:08   作者:空指针异常1  
这篇文章主要介绍了Redis数据结构SortedSet的底层原理解析,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

概述

一些常用命令

  • 存储:zadd key score value
  • 获取:zrange key start end
  • 获取:同时获取分数:zrange key start end with score
  • 删除:zrem key value

存储的时候我们可以发现,是有一个score(分数)的,这个就是用来排序的字段。

实现

先说结论,SortedSet底层,根据配置会在不同的时候选用两种不同的数据结构zset,或ziplist进行存储:

首先,我们来看几个参数:

zset-max-ziplist-entries 128
zset-max-ziplist-value 64
if (
    field-value对的数量 > ziplist.entries.size ||
    任意一个filed或value长度 > zset-max-ziplist-value
) {
    // 使用 zset 进行存储
} else {
    // 使用 ziplist 进行存储

zset的结构如下:

typedef struct zset {
    dict *dict;
    zskiplist *zsl;
} zset

可以发现,是由字典+跳跃表实现的。

  • zset 结构体里有两个元素,一个是 dict,用来维护 数据 到 分数 的关系,一个是 zskiplist,用来维护 分数所在链表 的关系
  • dict 里通过维护 哈希表 存储了 张三=>100,李四=>90 的分数关系。

而跳表则是排序的关键

跳跃表

先上图:

我们知道,链表的检索效率是非常低的,如果要拿到100条数据中间的数据,则需要遍历50个数据才行,为了解决这个问题,跳表应运而生

如上图,就是常规的跳表,会在原有的数据上加上若干层,指向当前层的下一个节点。

跳表的插入

如上图所示:其实每个节点的层数是随机的,而且新插入一个节点不会影响其它节点的层数。因此,插入操作只需要修改插入节点前后的指针,而不需要对很多节点都进行调整。这就降低了插入操作的复杂度。实际上,这是skiplist跳表的一个很重要的特性,这让它在插入性能上明显优于平衡树的方案。

如下图,假如我们需要查询23,查询的路径如下。

事实上,在插入之前也要先经历一个类似的查找过程,在确定插入位置后,再完成插入操作。

这也是SortedSet实现排序的原理。

压缩列表

压缩列表 ziplist 是为 Redis 节约内存而开发的。

压缩列表是由一系列特殊编码的连续内存块组成的顺序型数据结构,一个压缩列表可以包含任意多个节点 (entry),每个节点可以保存 一个字节数组 或者 一个整数值 。

1、zl bytes:用于记录整个压缩列表占用的内存字节数

2、zl tail:记录要列表尾节点距离压缩列表的起始地址有多少字节

3、zl len:记录了压缩列表包含的节点数量。

4、entryX:要说列表包含的各个节点

5、zl end:用于标记压缩列表的末端

压缩列表是一种为了节约内存而开发的顺序型数据结构

压缩列表被用作列表键和哈希键的底层实现之一

压缩列表可以包含多个节点,每个节点可以保存一个字节数组或者整数值

添加新节点到压缩列表,可能会引发连锁更新操作。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 深入了解Redis连接数问题的现象和解法

    深入了解Redis连接数问题的现象和解法

    一般情况 Redis 连接数问题并不常见,但是当你业务服务增加、对 Redis 的依赖持续增强的过程中,可能会遇到很多 Redis 的问题,这个时候,Redis 连接数可能就成了一个常见的问题,在本章节,希望能够带大家了解Redis连接数问题的现象和解法,需要的朋友可以参考下
    2023-12-12
  • redis实现sentinel哨兵架构的方法

    redis实现sentinel哨兵架构的方法

    哨兵是一个分布式系统,可以在一个架构中运行多个哨兵(sentinel) 进程,这些进程使用流言协议(gossip protocols)来接收关于Master主服务器是否下线的信息,这篇文章主要介绍了redis实现sentinel哨兵架构,需要的朋友可以参考下
    2022-11-11
  • Redis Hash序列化存储的问题及解决方案

    Redis Hash序列化存储的问题及解决方案

    这篇文章主要介绍了Redis Hash序列化存储的问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • 详解redis数据结构之压缩列表

    详解redis数据结构之压缩列表

    这篇文章主要介绍了详解redis数据结构之压缩列表的相关资料,压缩列表在redis中的结构体名称为ziplist,其是redis为了节约内存而声明的一种数据结构,需要的朋友可以参考下
    2017-05-05
  • 详解Redis数据结构之跳跃表

    详解Redis数据结构之跳跃表

    这篇文章主要介绍了Redis数据结构中的跳跃表的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-11-11
  • YII2框架手动安装Redis扩展的过程

    YII2框架手动安装Redis扩展的过程

    这篇文章主要介绍了YII2框架手动安装Redis扩展的过程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-06-06
  • Redis中键的过期删除策略深入讲解

    Redis中键的过期删除策略深入讲解

    这篇文章主要给大家介绍了关于Redis中键的过期删除策略的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-09-09
  • Redis结合Lua脚本实现分布式锁详解

    Redis结合Lua脚本实现分布式锁详解

    Lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 本文主要为大家介绍了Redis如何结合Lua脚本实现分布式锁,需要的可以参考下
    2024-02-02
  • Java Socket实现Redis客户端的详细说明

    Java Socket实现Redis客户端的详细说明

    socket编程是一门技术,它主要是在网络通信中经常用到.这篇文章主要介绍了如何用Java Socket实现一个简单的Redis客户端,需要的朋友可以参考下
    2021-05-05
  • Redis中Redisson红锁(Redlock)使用原理

    Redis中Redisson红锁(Redlock)使用原理

    本文主要介绍了Redis中Redisson红锁(Redlock)使用原理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08

最新评论