暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Redis tips(五)——内存

爱可可的人生记录仪 2019-12-03
150

Redis所有的数据都存在内存中,因此如何高效利用Redis内存非常重要。


1.内存消耗

1.1 内存使用统计

info memory可以获取内存的相关指标,主要关注以下几个指标:

used_memory: 分配的内存总量,内部存储所有数据的内存占用量。

used_memory_rss: 操作系统角度显示redis占用的物理内存总量。

mem_fragmentation_ratio: used_memory_rss/used_memory,表示内存碎片率。

当内存碎片率大于1,说明多出来的内存没有用于数据存储,如果相差很大,说明碎片率严重

当内存碎片率小于1,一般由于swap到硬盘导致,会导致Redis性能变差,需要特别关注。


1.2 内存消耗划分(自身内存+对象内存+缓冲内存+内存碎片)

自身内存:Redis自身内存消耗非常少,可以忽略不计。

对象内存:占用最大的一块,存储用户所有数据。可以简单理解为sizeof(keys)+sizeof(values)

缓冲内存:客户端缓冲(详见客户端那一篇),复制积压缓冲区(详见复制那一篇),AOF缓冲区(空间占用很小)

内存碎片:默认内存分配器采用jemalloc,可选的还有:glibc、tcmalloc。分配内存策略一般采用固定范围的内存块进行分配。正常的碎片率在1.03左右。可能导致高碎片的操作:频繁做更新操作,大量的过期键删除。常用解决方法:数据对齐,安全重启。


1.3 子进程内存消耗

主要指重写时fork的内存消耗。根据实际要预留一些内存防止溢出。设置vm.overcommit_memory=1允许内核可以分配所有的物理内存。关闭THP,防止copy-on-write期间内存过度消耗。


2.内存管理

2.1 内存上限

使用maxmemory参数限制最大可用内存(建议所有的redis服务器都要设置),对应的是used_memory统计的内存。实际消耗会更大,规划时务必预留一些内存。可以通过config set maxmemory来进行动态修改。


2.2 内存回收策略

删除过期的键对象:惰性删除和定时任务删除

内存使用达到maxmemoy上限时触发内存溢出控制策略,受maxmemory-policy参数控制(可以通过config set设置),策略有六种,默认noeviction(拒绝所有人写入,只响应读),其他策略上网看吧。


3.内存优化

3.1 redisObject对象

Redis存储的所有值对象在内部定义为redisObject的结构体。

type:4 ——对象类型

encoding:4 ——内部编码类型

lru:REDSIS_LRU_BITS ——LRU计时时钟

int refcount ——引用计数器

void *ptr——数据指针

3.2 缩减键值对象

降低内存的使用直接的方法就是缩减键值的长度

3.3 共享对象池

Redis内部维护[0-9999]的整数对象池。开发中在满足需求的前提下,尽量使用整数对象以节省内存。相同数据内存可以降低30%以上。

3.4 字符串优化

尽量减少字符串频繁修改操作如append、setrange,改为直接使用set

3.5 编码优化

使用ziplist压缩编码优化hash、list等结构,注重效率和空间的平衡

使用intset编码优化整数集合

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


题外话:innobackupex全量恢复的时候,最后一步--copy-back没有必要,直接把所有数据文件mv到mysql的data目录即可。这一章有关Redis编码的部分目前理解能力有限,就只能记个大概,遇到的时候再深入研究吧。


今天,和一个大佬(两个月就在北京有房)聊了几句,感受颇深。机会只留给有准备的人,对绝大多数人来说,你除了学习,真的没有任何机会。切记,人外有人,与君共勉。


参考资料:付磊、张益军.Redis开发与运维.北京:机械工业出版社,2017.02.



部分内容来自网络,如有侵权请联系作者删除。


文章转载自爱可可的人生记录仪,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论