Redis数据结构介绍

概要

Redis 对外的数据结构包括:字符串(string)、哈希(hash)、列表(list)、集合(set)以及有序集合(zset)。这些数据结构都有对应的 API 可以在客户端使用。如上每一种数据结构在 Redis 内部又对应不只一种内部编码实现。Redis 根据存储的数据选择比较合适的内部编码以实现内存与性能之间的平衡。

键值的数据类型通过 type 命令查看,内部编码通过 object encoding 命令查看:

127.0.0.1> set a b
OK
127.0.0.1> type a
string 
127.0.0.1> object encoding a
"embstr"

字符串(string)

字符串类型的值可以是字符串(简单字符串,复杂字符串如(JSON、XML),数字(整数、浮点数),甚至是二进制(图片、视频、音频)),值最大不能超过 512MB。

字符串类型的内部编码有 3 种:
int:键值8 个字节的长整型
embstr:键值是小于等于 39 个字节的字符串
raw:键值是大于 39 个字节的字符串

哈希(hash)

哈希类型是指键值本身又是一个键值对,形如:value = {{field1=value1},{field2=value2}}

哈希类型的内部编码有 2 种:
ziplist:当哈希类型的元素个数小于 hash-max-ziplist-entries 配置(默认 512 个),同时所有的值都小于 hash-max-ziplist-value 配置(默认 64 字节)时。ziplist 更加节省内存。
hashtable:当不满足 ziplist 条件,ziplist 的读写效率会下降,此时,使用 hashtable 作为内部编码,hashtable 的读写时间复杂度是 O(1)。

开发提醒:为了节省内存,可以将一个大的哈希拆分成若干小的哈希来满足 ziplist 条件。

列表(list)

列表用来存储多个有序的字符串,列表中的每个字符串称之为一个元素,列表中的元素可以重复,一个列表最多可以存储 2^31 - 1 个元素。
列表类型的内部编码有 3 种:
ziplist:当列表类型的元素个数小于 list-max-zip-entries 配置(默认 512 个),同时列表中的每个元素的值都小于 list-max-ziplist-value 配置(默认 64 字节),ziplist 更加节省内存。
linkedlist:当不满足 ziplist 条件,内部编码使用 linkedlist 实现。
quicklist:是一个以 ziplist 为节点的 linkedlist,结合了 ziplist 和 linkedlist 的优点。从 Redis 3.2 版本开始,新增了这种更加优秀的列表内部编码实现。

开发提醒:
lpush + lpop = Stack(栈)
lpush + rpop = Queue(队列)
lpush + brpop = Message Queue(消息队列)

集合(set)

集合用来存储多个字符串,集合中最多可以存储 2^32 -1 个元素。相比列表,集合是无序且不重复的,可以实现多个集合之间取交集,并集,差集。
集合的内部编码有 2 种:
intset:当集合中的元素都是整数且元素个数小于 set-max-intset-entries 配置(默认 512 个),Redis 使用 intset 作为集合的内部编码实现,intset 更加节省内存。
hashtable:当不满足 intset 条件,Redis 使用 hashtable 作为内部编码实现。

有序集合(zset)

有序集合拥有集合的特性,除此之外,有序集合中的元素可以排序,有序集合通过给元素设置一个分数(score)来作为排序依据。
有序集合的内部编码有 2 种:
ziplist:当有序集合的元素个数小于 zset-max-ziplist-entries 配置(默认 512 个),同时每个元素的值小于 zset-max-ziplist-value 配置(默认 64 字节),ziplist 相对比较节省内存。
skiplist:当 ziplist 条件不满足时,有序集合使用 skiplist 作为内部编码。

总结

了解 Redis 的数据结构和内部编码实现有助于在缓存数据时进行合理的设计,选择合适的数据结构进行数据缓存,同时结合内部编码实现的条件分类,做到相对节省内存。

Redis 这种数据结构和内部编码实现分离的设计有两个好处:第一,每一种数据结构可以对应多个内部编码,根据不同的键值选择更加高效的内部编码;第二,内部编码的升级迭代对外部来说是透明的,客户端无感知。

6 声望
0 粉丝
0 条评论
推荐阅读
JDK 的 SPI 机制
SPI 是 Service Provider Interface 的简称,一般是指由厂商来实现并部署在应用程序 ClassPath 下的服务提供者接口。

阿白阅读 323

Redis 发布订阅模式:原理拆解并实现一个消息队列
“65 哥,如果你交了个漂亮小姐姐做女朋友,你会通过什么方式将这个消息广而告之给你的微信好友?““那不得拍点女朋友的美照 + 亲密照弄一个九宫格图文消息在朋友圈发布大肆宣传,暴击单身狗。”像这种 65 哥通过朋...

码哥字节6阅读 1.3k

封面图
Redis高可用之哨兵机制实现细节
在上一篇的文章《Redis高可用全景一览》中,我们学习了 Redis 的高可用性。高可用性有两方面含义:一是服务少中断,二是数据少丢失。主从库模式和哨兵保证了服务少中断,AOF 日志和 RDB 快照保证了数据少丢失。

杨同学technotes4阅读 1.1k

1.5万字总结 Redis 常见面试题&知识点
Redis 是一个基于 C 语言开发的开源数据库(BSD 许可),与传统数据库不同的是 Redis 的数据是存在内存中的(内存数据库),读写速度非常快,被广泛应用于缓存方向。并且,Redis 存储的是 KV 键值对数据。

JavaGuide3阅读 797

封面图
Redis的数据被删除,占用内存咋还那么大?
通过 CONFIG SET maxmemory 100mb 或者在 redis.conf 配置文件设置 maxmemory 100mb Redis 内存占用限制。当达到内存最大值值,会触发内存淘汰策略删除数据。

码哥字节2阅读 608

封面图
深入理解redis——缓存双写一致性之更新策略探讨
1.Redis缓存双写一致性我们都知道,只要我们使用redis,就会遇到缓存与数据库的双存储双写,那么只要是双写,就一定会有数据一致性问题,为了保证双写一致性,我们要先动redis还是mysql?

苏凌峰阅读 2.7k

Reids的BigKey和HotKey
Redis big key problem,实际上不是大Key问题,而是Key对应的value过大,因此严格来说是Big Value问题,Redis value is too large (key value is too large)。

Java架构师2阅读 475

6 声望
0 粉丝
宣传栏