Redis 数据类型

概述

数据类型实际描述的是 value 的类型,key 都是 string,常见数据类型(value)有

  1. string(embstr、raw、int)

  2. list(quicklist,由多个 ziplist 双向链表组成)

  3. hash(ziplist、hashtable)

  4. set(intset、hashtable)

  5. sorted set(ziplist、skiplist)

  6. bitmap

  7. hyperloglog

每一种类型都用 redisObject 结构体来表示,每种类型根据情况不同,有不同的编码 encoding(即底层数据结构)

1、String

  1. 如果字符串保存的是整数值,则底层编码为 int,实际使用 long 来存储

  2. 如果字符串保存的是非整数值(浮点数字或其它字符)又分两种情况

    1. 长度 <= 39 字节,使用 embstr 编码来保存,即将 redisObject 和 sdshdr 结构体保存在一起,分配内存只需一次

    2. 长度 > 39 字节,使用 raw 编码来保存,即 redisObject 结构体分配一次内存,sdshdr 结构体分配一次内存,用指针相连

  3. sdshdr 称为简单动态字符串,实现上有点类似于 java 中的 StringBuilder,有如下特性

    1. 单独存储字符长度,相比 char* 获取长度效率高(char* 是 C 语言原生字符串表示)

    2. 支持动态扩容,方便字符串拼接操作

    3. 预留空间,减少内存分配、释放次数(< 1M 时容量是字符串实际长度 2 倍,>= 1M 时容量是原有容量 + 1M)

    4. 二进制安全,例如传统 char* 以 \0 作为结束字符,这样就不能保存视频、图片等二进制数据,而 sds 以长度来进行读取

 

2、List

  1. 3.2 开始,Redis 采用 quicklist 作为其编码方式,它是一个双向链表,节点元素是 ziplist

    1. 由于是链表,内存上不连续

    2. 操作头尾效率高,时间复杂度 O(1)

    3. 链表中 ziplist 的大小和元素个数都可以设置,其中大小默认 8kb

  2. ziplist 用一块连续的内存存储数据,设计目标是让数据存储更紧凑,减少碎片开销,节约内存,它的结构如下

    1. zlbytes – 记录整个 ziplist 占用字节数

    2. zltail-offset – 记录尾节点偏移量

    3. zllength – 记录节点数量

    4. entry – 节点,1 ~ N 个,每个 entry 记录了前一 entry 长度,本 entry 的编码、长度、实际数据,为了节省内存,根据实际数据长度不同,用于记录长度的字节数也不同,例如前一 entry 长度是 253 时,需要用 1 个字节,但超过了 253,需要用 5 个字节

    5. zlend – 结束标记

  3. ziplist 适合存储少量元素,否则查询效率不高,并且长度可变的设计会带来连锁更新问题

 

3、Hash

  1. 在数据量较小时,采用 ziplist 作为其编码,当键或值长度过大(64)或个数过多(512)时,转为 hashtable 编码

  2. hashtable 编码

    • hash 函数,Redis 5.0 采用了 SipHash 算法

    • 采用拉链法解决 key 冲突

    • rehash 时机

      ① 当元素数 < 1 * 桶个数时,不扩容

      ② 当元素数 > 5 * 桶个数时,一定扩容

      ③ 当 1 * 桶个数 <= 元素数 <= 5 * 桶个数时,如果此时没有进行 AOF 或 RDB 操作时

      ④ 当元素数 < 桶个数 / 10 时,缩容

    • rehash 要点

      ① 每个字典有两个哈希表,桶个数为 $2^n$,平时使用 ht[0],ht[1] 开始为 null,扩容时新数组大小为元素个数 * 2

      渐进式 rehash,即不是一次将所有桶都迁移过去,每次对这张表 CRUD 仅迁移一个桶

      active rehash,server 的主循环中,每 100 ms 里留出 1s 进行主动迁移

      ④ rehash 过程中,新增操作 ht[1] ,其它操作先操作 ht[0],若没有,再操作 ht[1]

      ⑤ redis 所有 CRUD 都是单线程,因此 rehash 一定是线程安全的

 

4、Sorted Set

(1)在数据量较小时,采用 ziplist 作为其编码,按 score 有序,当键或值长度过大(64)或个数过多(128)时,转为 skiplist + hashtable 编码,同时采用的理由是

  • 只用 hashtable,CRUD 是 O(1),但要执行有序操作,需要排序,带来额外时间空间复杂度

  • 只用 skiplist,虽然范围操作优点保留,但时间复杂度上升

  • 虽然同时采用了两种结构,但由于采用了指针,元素并不会占用双份内存

(2)skiplist 要点:多层链表、排序规则、 backward、level(span,forward)

  • score 存储分数、member 存储数据、按 score 排序,如果 score 相同再按 member 排序

  • backward 存储上一个节点指针

  • 每个节点中会存储层级信息(level),同一个节点可能会有多层,每个 level 有属性:

    • foward 同层中下一个节点指针

    • span 跨度,用于计算排名,不是所有跳表都实现了跨度,Redis 实现特有

(3)多层链表可以加速查询,规则为,从顶层开始

  1. 大于同层右边的,继续在同层向右找
  2. 相等找到了
  3. 小于同层右边的或右边为 NULL,下一层,重复 1、2 步骤
  • 以查找【崔八】为例

    1. 从顶层(4)层向右找到【王五】节点,22 > 7 继续向右找,但右侧是 NULL,下一层

    2. 在【王五】节点的第 3 层向右找到【孙二】节点,22 < 37,下一层

    3. 在【王五】节点的第 2 层向右找到【赵六】节点,22 > 19,继续向右找到【孙二】节点,22 < 37,下一层

    4. 在【赵六】节点的第 1 层向右找到【崔八】节点,22 = 22,返回

注意

  • 数据量较小时,不能体现跳表的性能提升,跳表查询的时间复杂度是 $log_2(N)$,与二叉树性能相当  

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Redis支持多种数据类型,包括string、hash、list、set和sorted set等。其中,string是最基本、最简单的数据类型,用于存储字符串。 Hash是用于存储键对的数据结构,其中的value只能存储字符串,不允许存储其他数据类型,也不存在嵌套现象。每个hash可以存储232 - 1个键对,并可以灵活添加或删除对象属性。但需要注意的是,hash类型并不适合存储大量对象,也不应该将hash作为对象列表使用,因为遍历整体数据的效率可能会较低。 除了string和hash类型,Redis还支持list、set和sorted set等数据类型。List是一个有序的字符串列表,可以进行插入、删除和查找等操作。Set是一个无序的字符串集合,可以进行元素的添加、删除和查找操作,并且不允许重复元素的存在。Sorted Set是一个有序的字符串集合,每个元素都有一个对应的score,可以根据score进行排序和范围查找。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Redis 数据类型](https://blog.csdn.net/weixin_52851967/article/details/122670564)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

悠然予夏

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

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

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

打赏作者

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

抵扣说明:

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

余额充值