Redis内存优化二

2020-04-11  本文已影响0人  0d3f575c8bef

这一节我们继续说Redis内存优化  上一节我们说了key的优化以及整数对象池的相关知识

下面我们说一说字符串的优化

字符串的优化

Redis中使用的字符串实现 叫SDS 结构如下

    len  已用长度

    feeLen 未用长度

    char[] 字节数组

获取这几个属性的时间复杂度都是O(1)

同时我们要知道 SDS的内存预分配机制 就是第一次set的时候 len就是字符串长 freeLen=0

当采用append等命令修改字符串时间redis为对字符串的空间进行扩容 然后再把追加的字符串放入其中,这种预分配机制扩容的长度通常要大于追加的字符串,这就会造成内存的浪费 所以在使用的时候尽量直接set 不要追加 避免重复预分配内存造成的损耗

编码优化

redis提供了5种数据类型  string hash  list set zset  每种类型在redis实现中都至少有两种内部编码实现

为什么这么做? 最重要的原因是为了追求效率与空间的平衡  不同的编码所占用的内存空间差异很大 所以合理的使用内部编码对于内存优化有很大的帮助   下面我们来聊一聊

查看当前key的内部编码实现   object encoding key  

例 

set hello 'world'      

object encoding hello  ->  embstr    说明此时redis内部使用embstr这种实现来存储world字符串

同一种数据类型既然有两种或以上的内部 实现 那使用哪一种由什么确定呢?

通常来说跟数据长度及大小有关

举例:

对于hash这种类型   

当存储的哈希类型元素个数小于hash-max-ziplist-entries配置(默认512个),同时所有值都小于hash-max-ziplist-value配置(默认64字节)  时使用的内部实现 是ziplist  一旦其中某个参数超过阈值 内部实现就更改为 hashtable   ,而hashtable会占用更大的内存空间  

编码的转换是在redis写入的时候自动完成的,并且只能从小内存编码向大内存编码转换 不能降级

再来简单说一说  ziplist这种编码  

ziplist主要特点是占用内存空间 小 它采用线性连续的内存空间

同时它可以作为多种数据类型的实现 如 hash  list  zset

ziplist 内部有多个entry 每个entry保存具体的数据    

新增和删除操作会涉及内存的重新分配和释放 加大了操作的复杂性 

同时读写操作的复杂度为O(n2)  所以适用于小对象和长度有限的数据使用

最后还有一点  在使用redis的过程中我们要尽量控制键的数量  

如果键过多也会消耗大量内存  

键过多的情况下我们可以考虑会使用hash来存储  把一部键当做hash的field来存储

当然要确保hash元素不要过多  保证底层的实现是使用ziplist的 否则会得不偿失

使用ziplist+hash优化keys后,如果想使用超时删除功能,开发人员可以存储每个对象写入的时间,再通过定时任务使用hscan命令扫描数据,找出hash内超时的数据项删除即可。

上一篇 下一篇

猜你喜欢

热点阅读