Redis内存管理和优化02

 

 

Redis内存管理和优化02_第1张图片   

好好整理了一下关于reids内存优化的知识,总算对redis内存管理有了一个初步的认识。

一.内存消耗分析

Redis进程内消耗主要包括:自身内存+对象内存+缓冲内存+内存碎片,其中Redis空进程自身内存消耗非常少,通常used_memory_rss在3MB左右,used_memory在800KB左右,一个空的Redis进程消耗内存可以忽略不计。

Redis内存管理和优化02_第2张图片

 

    1.对象内存

        数据都采用key-value数据类型,每次创建键值对时,至少创建两个类型对象:key对象和value对象。对象内存消耗可以简单理解为sizeofkeys+sizeofvalues)。键对象都是字符串,在使用Redis时很容易忽略键对内存消耗的影响,应当避免使用过长的键。

    2.缓冲内存

        缓冲内存主要包括:客户端缓冲、复制积压缓冲区、AOF缓冲区。

 

    3.内存碎片

        比如当保存5KB对象时jemalloc可能会采用8KB的块存储,而剩下的3KB空间变为了内存碎片不能再分配给其他对象存储。内存碎片问题虽然是所有内存服务的通病,但是jemalloc针对碎片化问题专门做了优化,一般不会存在过度碎片化的问题,正常的碎片率(mem_fragmentation_ratio)在1.03左右。

    4.子进程内存消耗问题

        Redis产生的子进程并不需要消耗1倍的父进程内存,实际消耗根据期间写入命令量决定,但是依然要预留出一些内存防止溢出。

 

二.内存管理

    1.限制内存使用上限

    2.内存回收策略

        Redis的内存回收机制主要体现在以下两个方面

·     删除到达过期时间的键对象。

·      内存使用达到maxmemory上限时触发内存溢出控制策略。

   3.删除过期的健

        Redis所有的键都可以设置过期属性,内部保存在过期字典中。由于进程内保存大量的键,维护每个键精准的过期删除机制会导致消耗大量的CPU,对于单线程的Redi来说成本过高,因此Redis采用惰性删除和定时任务删除机制实现过期键的内存回收。

        惰性删除:

惰性删除:惰性删除用于当客户端读取带有超时属性的键时,如果已经超过键设置的过期时间,会执行删除操作并返回空,这种策略是出于节省CPU成本考虑,不需要单独维护TTL链表来处理过期键的删除。但是单独用这种方式存在内存泄露的问题,当过期键一直没有访问将无法得到及时删除,从而导致内存不能及时释放

正因为如此,Redis还提供另一种定时任务删除机制作为惰性删除的补充

定时任务删除:Redis内部维护一个定时任务,默认每秒运行10次(通过配置hz控制)。定时任务中删除过期键逻辑采用了自适应算法,根据键的过期比例、使用快慢两种速率模式回收键。

4.定时删除key策略

流程说明

1)定时任务在每个数据库空间随机检查20个键,当发现过期时删除对应的键

2)如果超过检查数25%的键过期,循环执行回收逻辑直到不足25%或运行超时为止,慢模式下超时时间为25毫秒。

3)如果之前回收键逻辑超时,则在Redis触发内部事件之前再次以快模式运行回收过期键任务,快模式下超时时间为1毫秒且2秒内只能运行1次。

 

三.内存优化

Redis内存管理和优化02_第3张图片

 

 

1.redisObject

2.共享内存池

    共享对象池是指Redis内部维护[0-9999]的整数对象池。无论使用多少次0-9999中的整数,只占用一份0-9999的内存。

3.hash结构内存优化与关键点

同样的数据使用ziplist编码的hash类型存储比string类型节约内存

·节省内存量随着value空间的减少越来越明显

·hash-ziplist类型比string类型写入耗时,但随着value空间的减少,耗时逐渐降低。

4.hash结构健的设计

·1)当键离散度较高时,可以按字符串位截取,把后三位作为哈希的field,之前部分作为哈希的键。如:key=1948480哈希key=group:hash:1948,哈希field=480

2)当键离散度较低时,可以使用哈希算法打散键,如:使用crc32key&10000函数把所有的键映射到“0-9999”整数范围内,哈希field存储键的原始值

5.使用hash结构需要提前规避的问题

·客户端需要预估键的规模并设计hash分组规则,加重客户端开发成本

·hash重构后所有的键无法再使用超时(expire)和LRU淘汰机制自动删除,需要手动维护删除

·对于大对象,如1KB以上的对象,使用hash-ziplist结构控制键数量反而得不偿失。

不过瑕不掩瑜,对于大量小对象的存储场景,非常适合使用ziplist编码的hash类型控制键的规模来降低内存。

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

 

总结:

1Redis实际内存消耗主要包括:键值对象、缓冲区内存、内存碎片

2)通过调整maxmemory控制Redis最大可用内存。当内存使用超出时,根据maxmemory-policy控制内存回收策略。

3)内存是相对宝贵的资源,通过合理的优化可以有效地降低内存的使用量,内存优化的思路包括

     ·精简键值对大小,键值字面量精简,使用高效二进制序列化工具

    ·使用对象共享池优化小整数对象。 ·数据优先使用整数,比字符串类型更节省空间

·优化字符串使用,避免预分配造成的内存浪费

·使用ziplist压缩编码优化hashlist等结构,注重效率和空间的平衡。 ·使用intset编码优化整数集合

·使用ziplist编码的hash结构降低小对象链规模。

 

 

你可能感兴趣的:(redis)