String类型是我们在使用Redis最常考虑使用的类型。它有没有缺点呢?该如何优化呢?
String类型保存的是二进制字节流也就是"万金油"类型。除了记录实际数据,String类型还需要额外的内存空间记录数据长度、空间使用等这些元信息。当实际保存的数据较小时,元数据的空间开销就显得比较大了。
- buf 字节数组,保存实际数据。为了字节数组的结束,Redis会自动在数据最后加上"\0",额外占用一个字节开销。
- len 占4字节,表示buf已用长度
- alloc 占4字节 表示buf的实际分配长度,一般大于len
除了SDS的额外开销,还有RedisObject结构,保存了比如最后一次访问时间、引用次数等8字节元数据以及8字节ptr字节指针
String的三种编码方式 int、embstr、raw
jemalloc分配内存会根据什么字节数N,找一个比N大,最接近N的2次幂数作为分配空间,这样可以减少频繁分配次数。但也可能造成内存碎片。
Redis还有一种底层数据结构ziplist,非常节省内存。表头有zlbytes、zltail、zllen 列长度、列表尾偏移量、列表的entry个数。表尾有zlend表示列表结束
每一个entry又包含prev_len entry长度 len 自身长度4字节 encoding 编码方式 1字节 content 实际数据
小tips
小数据键值对可以使用Hash二级编码的方法保存数据 把原来的的key分为两半 一部分作为Hash的key 一部分做为内部value的key。且第二部分讲究用3位数来做key,使得每一个Hash都小于1000个元素,就可以很好的利用has底层的ziplist结构。
hash-max-ziplist-entries:表示用压缩列表保存时哈希集合中的最大元素个数。hash-max-ziplist-value:表示用压缩列表保存时哈希集合中单个元素的最大长度。
这两个阈值超过则会使用哈希表来保存。也就在保存空间上没那么高效了。