String是Redis中最常见的数据类型,基本编码方式是RAW,基于简单动态字符串(SDS)实现。存储上限为512mb。
但是如果存储的SDS长度小于44字节,就会采用 EMBSTR 编码,此时object head 与 SDS就是一段连续的空间了。申请内存只需要调用一次内存分配函数,效率更高,如下图:
如果存储的字符串是整数值,并且大小在LONG_MAX范围内,就会采用 INT 编码:直接将数据保存在RedisObject的ptr指针位置(刚好8字节),就不需要SDS了。
Redis类型可以从首、尾操作列表中的元素。一提到首尾,首先想到的就是链表, 双端链表 。 ZipList 可以避免常规链表的指针所带来的内存消耗,但是申请内存的时候必须要连续内存,所以数据量上限不是很高。 QuickList 是普通链表 + ZipList的结合,可以从双端访问,内存占用也很低,内部包含多个ZipList,存储上限高。
3.2版本之后,Redis统一采用QuickList来实现List。
Set是Redis中的单列集合,满足以下特点:
可以看出,Set对查询元素的效率要求非常高,什么数据结构可以满足?我们可以使用 HashTable ,也就是Redis中的 Dict 。但是我们的Set只需要保存元素的值,不像Dict有key和value两个数据,所以我们使用Dict中的key来存储元素,value统一为null。
但是HashTable中会有很多内存碎片,而且会有大量的指针很浪费内存,当存储的 所有数据都是整数 ,并且元素数量不超过 set-max-inset-entries 时,Set会采用 IntSet 编码,来节省内存。
ZSet也就是SortedSet,每一个元素都要指定一个score值和member值:
那么,很明显我们要为ZSet底层挑选的数据结构要满足 键值存储 、 键必须唯一 、 可排序 这几个功能。 SkipList 可以排序,也可以做键值存储; Dict 可以键值存储,也可以使用key找value。所以我们 同时使用这两种底层的数据结构 ,就能实现ZSet的功能了。
因为使用了两种底层数据结构来存储数据,所以内存占用很高。所以当元素数量不多的时候,使用 Dict 和 SkipList 的查询效率就不明显了,顺序遍历查找的速度也很快,而且同时使用两种底层数据结构很耗内存,所以我们可以采用 ZipList 结构来节省内存空间,同时查询的效率也不会很差。需要同时满足以下两个条件:
Hash结构和Redis中的Zset非常类似:
但也有区别,区别如下:
因此,Hash底层采用的编码与Zset也基本一致,只需要把排序有关的SkipList去掉即可。
Hash 底层采用的编码和Zset基本一致,就是把用来排序的SkipList去掉即可。
Hash结构也在数据量较小的时候使用ZipList编码,来节省内存,如果数据量超过规定的数量,元素数量超过hash-max-ziplist-entries 或者 任意entry大小超过了 hash-max-ziplist-value。那么结构就会转为 Dict 编码。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。