首页 > 数据库 >[微服务]redis数据结构

[微服务]redis数据结构

时间:2025-01-11 09:57:48浏览次数:3  
标签:服务 元素 redis 查询 SortedSet score 数据结构 节点 指针

介绍

我们常用的Redis数据类型有5种,分别是:

  • String
  • List
  • Set
  • SortedSet
  • Hash

还有一些高级数据类型,比如Bitmap、HyperLogLog、GEO等,其底层都是基于上述5种基本数据类型。因此在Redis的源码中,其实只有5种数据类型。

RedisObject

不管是任何一种数据类型,最终都会封装为RedisObject格式,它是一种结构体,C语言中的一种结构,可以理解为Java中的类。

结构大概是这样的:

可以看到整个结构体中并不包含真实的数据,仅仅是对象头信息,内存占用的大小为4+4+24+32+64 = 128bit

也就是16字节,然后指针ptr指针指向的才是真实数据存储的内存地址。所以RedisObject的内存开销是很大的。

属性中的encoding就是当前对象底层采用的数据结构编码方式

Redis中会根据存储的数据类型不同,选择不同的编码方式,共包含12种不同类型:

Redis中会根据存储的数据类型不同,选择不同的编码方式。每种数据类型的使用的编码方式如下

SkipList

SkipList(跳表)首先是链表,但与传统链表相比有几点差异:

  • 元素按照升序排列存储
  • 节点可能包含多个指针,指针跨度不同。

传统链表只有指向前后元素的指针,因此只能顺序依次访问。如果查找的元素在链表中间,查询的效率会比较低。而SkipList则不同,它内部包含跨度不同的多级指针,可以让我们跳跃查找链表中间的元素,效率非常高。

其结构如图:

我们可以看到1号元素就有指向3、5、10的多个指针,查询时就可以跳跃查找。例如我们要找大小为14的元素,查找的流程是这样的:

  • 首先找元素1节点最高级指针,也就是4级指针,起始元素大小为1,指针跨度为9,可以判断出目标元素大小为10。由于14比10大,肯定要从10这个元素向下接着找。
  • 找到10这个元素,发现10这个元素的最高级指针跨度为5,判断出目标元素大小为15,大于14,需要判断下级指针
  • 10这个元素的2级指针跨度为3,判断出目标元素为13,小于14,因此要基于元素13接着找
  • 13这个元素最高级级指针跨度为2,判断出目标元素为15,比14大,需要判断下级指针。
  • 13的下级指针跨度为1,因此目标元素是14,刚好于目标一致,找到。

这种多级指针的查询方式就避免了传统链表的逐个遍历导致的查询效率下降问题。在对有序数据做随机查询和排序时效率非常高。

跳表的结构体如下:

typedef struct zskiplist {
    // 头尾节点指针
    struct zskiplistNode *header, *tail;
    // 节点数量
    unsigned long length;
    // 最大的索引层级
    int level;
} zskiplist;

可以看到SkipList主要属性是header和tail,也就是头尾指针,因此它是支持双向遍历的。

跳表中节点的结构体如下:

typedef struct zskiplistNode {
    sds ele; // 节点存储的字符串
    double score;// 节点分数,排序、查找用
    struct zskiplistNode *backward; // 前一个节点指针
    struct zskiplistLevel {
        struct zskiplistNode *forward; // 下一个节点指针
        unsigned long span; // 索引跨度
    } level[]; // 多级索引数组
} zskiplistNode;

每个节点中都包含ele和score两个属性,其中score是得分,也就是节点排序的依据。ele则是节点存储的字符串数据指针。

其内存结构如下:

SkipList的特点:

  1. 跳跃表是一个有序的双向鲢表
  2. 每个节点都可以包含多层指针,层数是1到32之间的随机数不同层指针到下一个节点的跨度不同,层级越高,跨度越大增删改查效率与红黑树基本一致,实现却更简单。
  3. 但空间复杂度更高

SortedSet

面试题:

Redis的SortedSet底层的数据结构是怎样的?

  1. 首先Sortedset需要能存储score和member值,而且要快捷的根据member查询score,因此底层有一个哈希表,以member为键,以score为value
  2. 其次Sortedset还需要能根据score排序,因此底层还维护了一个跳表。
  3. 当需要根据member查询score时,就去哈希表中查询
  4. 当需要根据score排序查询时,则基于跳表查询

更多的细节

  1. SortedSet是有序集合,底层的存储的每个数据都包含element和score两个值。score是得分,element则是字符串值。SortedSet会根据每个element的score值排序,形成有序集合。

它支持的操作很多,比如:

  • 根据element查询score值
  • 按照score值升序或降序查询element
  1. 要实现根据element查询对应的score值,就必须实现element与score之间的键值映射。SortedSet底层是基于HashTable来实现的。
  2. 要实现对score值排序,并且查询效率还高,就需要有一种高效的有序数据结构,SortedSet是基于跳表实现的。
  3. 因为SortedSet底层需要用到两种数据结构,对内存占用比较高。因此Redis底层会对SortedSet中的元素大小做判断。如果元素大小小于128每个元素都小于64字节,SortedSet底层会采用ZipList,也就是压缩列表来代替HashTableSkipList
  4. 不过,ZipList存在连锁更新问题,因此而在Redis7.0版本以后,ZipList又被替换为Listpack(紧凑列表)。

Redis源码中zset,也就是SortedSet的结构体如下:

typedef struct zset {
    dict *dict; // dict,底层就是HashTable
    zskiplist *zsl; // 跳表
} zset;

其内存结构如图:

标签:服务,元素,redis,查询,SortedSet,score,数据结构,节点,指针
From: https://blog.csdn.net/CSDN20221005/article/details/145048741

相关文章

  • [微服务]redis分片集群搭建与优化
    介绍主从模式可以解决高可用、高并发读的问题。但依然有两个问题没有解决:海量数据存储高并发写要解决这两个问题就需要用到分片集群了。分片的意思,就是把数据拆分存储到不同节点,这样整个集群的存储数据量就更大了。Redis分片集群的结构如图:分片集群特征:集群中有多个ma......
  • 基于Springboot的社区便民服务平台设计和实现
    ......
  • 124.【C语言】数据结构之快速排序的小区间优化和非递归的解决方法
    目录1.小区间优化测试代码运行结果2.非递归的解决方法(重要!)递归产生的问题一般来说,递归改非递归有两种方法算法分析递归产生的二叉树栈的示意图先写代码框架再填写细节部分1.小区间优化回顾121.【C语言】数据结构之快速排序(未优化的Hoare排序存在的问题)以及......
  • 服务器多节点 Grafana、Prometheus 和 Node-Exporter Docker版本部署指南
    要在多台服务器上部署Grafana、Prometheus和Node-Exporter,并且其中一台服务器专门用于Grafana和Prometheus的部署1.准备工作服务器信息:Server1:用于部署Grafana和Prometheus。Server2-n:用于部署Node-Exporter。Docker:确保所有服务器上已安装Docker......
  • 【云安全】云服务-云服务器ECS-安全问题分析
    ECS概念弹性计算服务(ElasticComputeService,ECS)是一种云计算基础设施服务。它可以轻松地创建和管理虚拟服务器,为用户提供弹性的计算能力。弹性计算服务的主要特点包括:弹性伸缩:用户可以根据实际需求自动或手动调整计算能力。可以根据业务负载的变化,动态地增加或减少虚拟......
  • 冒险数据结构:峰谷序列(动态序列查找问题)
    先考虑这么一个问题:    如何求出一个序列在所有位置上的各个元素的前面和后面第一个比它小的元素位置。显然这个问题可以用单调栈来解决。        如上图所示,维护一个单调递增的序列,每当栈顶>当前元素时,就抛出栈顶,这时就找到了栈顶元素后面第一个小于它的......
  • C++并发编程之基于锁的数据结构的适用场合与需要考虑和注意的问题
    在C++多线程编程中,锁是一种常用的同步机制,用于保护共享数据,防止多个线程同时访问和修改,从而避免数据不一致或其他并发问题。基于锁的数据结构适用于多种并发编程场合,但同时也需要注意一些关键问题。1. 适用的并发编程场合锁在以下几种场合特别有用:1.1 保护共享数据当多个......
  • 配置tigerVNC,登陆远程服务器
    1.在远程服务器安装、配置(1)sudoaptupdatesudoaptinstallxfce4xfce4-goodies(2)安装TigerVNCsudoaptinstalltigervnc-standalone-server(3)配置vncvncpasswd(4)配置.vnc:vim~/.vnc/xstartup添加:cat.vnc/xstartup#!/bin/sh#启动D-Bus会话(如果未运行......
  • 05、Docker学习,常用安装:Mysql、Redis、Nginx、Nacos
    Docker学习,常用安装:Mysql、Redis、Nginx、Nacos一、Docker安装Mysql1、dockersearchmysql ##查找mysql版本都有哪些2、dockerpullmysql:5.6 ##下载5.6版本的mysql镜像3、dockerrun-p13306:3306--namemysql ##运行镜像生成容器-v/opt......
  • C/C++ 数据结构与算法【排序】 常见7大排序详细解析【日常学习,考研必备】带图+详细代
    常见7种排序算法冒泡排序(BubbleSort)选择排序(SelectionSort)插入排序(InsertionSort)希尔排序(ShellSort)归并排序(MergeSort)快速排序(QuickSort)堆排序(HeapSort)计数排序(CountingSort)算法复杂度1、冒泡排序冒泡排序是一种简单的排序算法,它重复地遍历要排序的数列,一次比......