5种基本数据类型
对于每种数据结构,实际上都有自己底层的 内部编码 实现,而且是多种实现。这样 Redis 会在合适的 场景 选择合适的 内部编码,如图所示:
可以看到,每种 数据结构 都有 两种以上 的 内部编码实现。例如 list
数据结构 包含了 linkedlist
和 ziplist
两种 内部编码。同时有些 内部编码,例如 ziplist
,可以作为多种外部数据结构的内部实现,可以通过 object encoding
命令查询内部编码:
1 | 127.0.0.1:6379> object encoding hello |
Redis 这样设计有两个好处:
其一:可以改进内部编码,而对外的数据结构和命令没有影响。例如:Redis3.2 提供的
quicklist
,结合了ziplist
和linkedlist
两者的优势,为列表类型
提供了一种更加高效的内部编码实现。其二:不同内部编码可以在不同场景下发挥各自的优势。例如
ziplist
比较节省内存,但是在列表元素比较多的情况下,性能会有所下降,这时候Redis会根据配置,将列表类型的内部实现 转换为linkedlist
。
String底层结构
字符串类型是Redis最基础的数据结构。字符串类型的值实际可以是字符串(简单 和 复杂 的字符串,例如 JSON、XML)、数字(整数、浮点数),甚至是 二进制(图片、音频、视频),但是值最大不能超过 512MB
。
字符串类型的内部编码有 3 种:
int:8个字节的长整型。
embstr:小于等于39个字节的字符串。
raw:大于39个字节的字符串。
Redis 会根据当前值的 类型 和 长度 决定使用哪种内部编码实现。
Hash底层结构
大部分编程语言都提供了哈希(hash)类型,它们的叫法可能是 哈希、字典、关联数组。在 Redis 中,哈希类型是指键值本身又是一个键值对结构。
压缩列表(ziplist)
当哈希类型元素个数 小于 hash-max-ziplist-entries
配置(默认 512 个)、同时所有值都小于 hash-max-ziplist-value
配置(默认 64 字节)时,Redis会使用ziplist
作为哈希的内部实现,ziplist
使用更加紧凑的结构实现多个元素的连续存储,所以在节省内存方面比hashtable
更加优秀.
哈希表(hashtable)
当哈希类型无法满足 ziplist
的条件时,Redis会使用hashtable
作为哈希的内部实现,因为此时 ziplist
的 读写效率 会下降,而 hashtable
的读写时间复杂度为 O(1)。
下面的示例演示了哈希类型的内部编码,以及相应的变化。
当field个数比较少,且没有大的value时,内部编码为ziplist
:
1 | 127.0.0.1:6379> hmset hashkey f1 v1 f2 v2 |
当有value大于64字节时,内部编码会由 ziplist
变为 hashtable
:
1 | 127.0.0.1:6379> hset hashkey f3 "one string is bigger than 64 byte...忽略..." |
当field个数超过 512,内部编码也会由 ziplist
变为hashtable
:
1 | 127.0.0.1:6379> hmset hashkey f1 v1 f2 v2 f3 v3 ... f513 v513 |
List底层结构
列表(list)类型是用来存储多个有序的字符串。在Redis中,可以对列表的两端进行 插入(push)和 弹出(pop)操作,还可以获取 指定范围 的 元素列表、获取 指定索引下标 的 元素 等, 一个列表最多可以存储 2^32 - 1
个元素。
列表是一种比较灵活的数据结构,它可以充当 栈 和 队列 的角色,在实际开发上有很多应用场景。
列表类型的内部编码有两种:
ziplist(压缩列表)
当列表的元素个数小于list-max-ziplist-entries
配置(默认512
个),同时列表中 每个元素的值都小于list-max-ziplist-value
配置时(默认64字节
),Redis会选用ziplist
来作为列表的内部实现来减少内存的使用。linkedlist(链表)
当列表类型无法满足ziplist
的条件时, Redis会使用linkedlist
作为列表的内部实现。
Set底层结构
集合(set)类型也是用来保存多个字符串元素,但和列表类型不一样的是,集合中不允许有重复元素,并且集合中的元素是无序的,不能通过索引下标获取元素, 一个集合最多可以存储 2^32 - 1
个元素。
集合类型的内部编码有两种:
- intset(整数集合)
当集合中的元素都是整数且元素个数小于set-max-intset-entries
配置(默认512个
)时,Redis会选用intset
来作为集合的内部实现,从而减少内存的使用。
- hashtable(哈希表)
当集合类型无法满足intset
的条件时,Redis会使用hashtable
作为集合的内部实现。
参考
深入剖析Redis系列(一) - Redis入门简介与主从搭建
深入剖析Redis系列(二) - Redis哨兵模式与高可用集群
深入剖析Redis系列(三) - Redis集群模式搭建与原理详解
深入剖析Redis系列(四) - Redis数据结构与全局命令概述