Redis数据结构 学习笔记 2022-3-21
Redis数据结构
1、String:
(底层:)简单动态字符串(SDS,simple dynamic string),是可以修改的字符串,类似于Java中的ArrayList;
(为什么选用SDS?)采用预分配冗余空间的方式来减少内存的频繁分配
(扩容:)当字符串长度小于 1M 时,扩容都是加倍扩容,如果超过 1M,扩容时一次只会增加 1M 的空间,字符串最大长度为 512M
(整体架构:)Redis 所有的数据结构都是以唯一的 key 字符串作为名称,然后通过这个唯一 key 值来获取相应的 value 数据。不同类型的数据结构的差异就在于 value 的结构不一样。但是这个key使用的结构,都是字符串类型
2、hash:
在redis中,hash类型是指Redis键值对中的值本身又是一个键值对结构,形如 value=[ {field1,value1},...,{fieldN,valueN} ]
如下图所示
(底层:)压缩列表(ziplist)与哈希表(hashtable);
(整体架构:)时间效率 和 空间效率 的平衡,压缩列表可以节省内存空间,哈希表查询效率高
只有当存储的数据量比较小的情况下,Redis 才使用压缩列表来实现字典类型
(压缩链表)需要满足两个条件:<总结:键值对数量少,值得数据小>
1、哈希类型元素个数(键值对个数)小于hash-max-ziplist-entries配置(默认512个)
2、所有值都小于hash-max-ziplist-value配置(默认64字节)
(特点:) ziplist使用更加紧凑的结构实现多个元素的连续存储,所以在 节省内存方面 比hashtable更加优秀
(转化:)当哈希类型无法满足ziplist的条件时,Redis会使用hashtable作为哈希的内部实现
(为什么?)因为此时ziplist的读写效率会下降,而hashtable的读写时间复杂度为O(1)
(本质:)时间效率 和 空间效率 的平衡
2.1、Redis压缩列表
压缩列表是Redis为了节约内存而开发的,是由一系列特殊编码的连续内存块组成的顺序型(sequential)数据结枃。一个压缩列表可以包含任意多个节点(entry),每个节点可以保存一个字节数组或者一个整数值,如下图
示例:
如上图,展示了一个总长为80字节,包含3个节点的压缩列表。如果我们有一个指向压缩列表起始地址的指针p,那么 表尾节点 的地址就是P+60。
2.2、Redis压缩列表节点的构成
每个压缩列表节点可以保存一个字节数组或者一个整数值。其中,字节数组可以是以下三种长度中的一种。
长度小于等于63(2^6-1)字节的字节数组;
长度小于等于16383(2^14-1)字节的字节数组
长度小于等于4294967295(2^32-1)字节的字节数组
整数值可以是以下6种长度中的一种
4位长,介于0至12之间的无符号整数
1字节长的有符号整数
3字节长的有符号整数
int16_t类型整数
int32_t类型整数
int64_t类型整数
、、、(学习地址:https://www.cnblogs.com/hunternet/p/11306690.html)
3、list:
(底层结构:)压缩链表 和 双向链表
(作用:)即可以当栈,也可以当队列
4、set:
(底层结构:)整数集合(Intset)和 哈希表
“整数集合(Intset)是Redis集合的底层实现之一,当一个集合中只包含整数,且这个集合中的元素数量不多时,redis就会使用整数集合intset作为集合的底层实现
(作用:1、存储集合性质得数据;2、进行集合间得操作)
5、zset(sorted set):
(底层结构:)跳表(skip list)<从 稀疏层次 往 紧密层次 上跳>,平均查找和插入时间复杂度都是O(logn)
通过维护一个多层次的链表,且每一层链表中的元素是前一层链表元素的子集(见右边的示意图);一开始时,算法在最稀疏的层次进行搜索,直至需要查找的元素在该层两个相邻的元素中间。这时,算法将跳转到下一个层次,重复刚才的搜索,直到找到需要查找的元素为止
跳表是用空间来换时间,跳表的效率比链表高了,但是跳表需要额外存储多级索引,所以需要的更多的内存空间
(作用:)zset可以保证数据不重复且有序,通过score来确定顺序