概述
本篇主要介绍 Redis 内存优化的一些技巧。
1.内存消耗
1、内存使用统计
Redis 可以通过 info memory 命令来查看内存使用情况,属性说明如下:
属性名 | 属性说明 |
---|---|
used_memory | Redis 分配器分配的内存量,也就是实际存储数据的内存总量 |
used_memory_human | 以可读格式返回 Redis 使用的内存总量 |
used_memory_rss | 从操作系统的角度,Redis 进程占用的总物理内存 |
used_memory_peak | 内存分配器分配的最大内存,代表 used_memory 的历史峰值 |
used_memory_peak_human | 以可读的格式显示内存消耗峰值 |
used_memory_lua | Lua 引擎所消耗的内存 |
mem_fragmentation_ratio | used_memory_rss/used_memory 比值,表示内存碎片率,used_memory_rss - used_memory 就是内存碎片的大小 |
mem_allocator | Redis 所使用的内存分配器,默认 jemalloc |
2、内存消耗划分
2.缓冲内存
1.客户端缓冲区
客户端分为普通客户端(Jedis)、slave 客户端、pubsub 客户端。
输入缓冲区:
流程:客户端 -> 命令(输入缓冲区) -> 处理命令
注意:最大 1GB,超过后会被强制断开,不可动态设置。
输出缓冲区:
输出缓冲区对应的配置规则是:client-output-buffer-limit < class> < hard limit> < soft limit> < soft seconds>
< class>:客户端类型,分为三种(a)normal 普通客户端;(b)slave 从节点用于复制,伪装成客户端;(c)pubsub 发布订阅客户端。
< hard limit>:如果客户端使用的输出缓冲区大于 < hard limit>,客户端会被立即关闭。
< soft limit> 和 < soft seconds>:如果客户端使用的输出缓冲区超过了 < soft limit> 并且持续了 < soft limit> 秒,客户端会被立即关闭。
普通客户端(Jedis)默认 client-output-buffer-limit normal 0 0 0,默认没有限制客户端缓冲,注意防止大的命令或者 monitor。
slave 客户端默认 client-output-buffer-limit slave 256mb 64mb 60,注意从节点不要超过 2 个。
pubsub 客户端默认 client-output-buffer-limit pubsub 32mb 8mb 60,使用场景并不多,注意根据实际场景适当调试。
2.复制缓冲区
此部分内存独享,考虑部分复制,默认 1 MB,可以设置更大。
3.AOF 缓冲区
AOF 重写期间,AOF 的缓冲区没有容量限制。
3.对象内存
key对象:不要过长,量大不容忽视;
value对象:ziplist、intset 等优化方式。
4.内存管理
1.内存设置上限
定义实例最大内存,便于管理机器内存,一般要预留 30%。动态调整内存上限的命令:
redis> config set maxmemory 6GB
redis> config rewrite
2.内存回收策略
1、删除过期键值
惰性删除:访问 key -> expired dict -> del key
定时删除:每秒运行 10 次,采样删除。
2、内存溢出控制策略
超过 maxmemory 后触发相应策略,由 maxmemory-policy 控制。
- Noeviction:默认策略,不会删除任何数据,拒绝所有写入操作并返回错误信息 “(error) OOM command not allowed when used memory”,此时 Redis 只响应读操作由 maxmemory-policy 控制。
- Volatile-lru:根据 LRU 算法删除设置了超时属性(expire)的键,直到腾出足够空间为止,如果没有可删除的键对象,回退到 Noeviction 策略。
- Allkeys-lru:根据 LRU 算法删除键,不管数据有没有设置超时属性,直到腾出足够空间为止。
- Allkeys-random:随机删除所有键,直到腾出足够空间为止。
- Volatile-random:随机删除过期键,直到腾出足够空间为止。
- Volatile-ttl:根据键值对象的 ttl 属性,删除最近将要过期的数据,如果没有,回退到 Noeviction 策略。
5.内存优化
1、合理的选择优化数据结构
2、客户端缓冲区内存优化
示例:一次内存暴增。Redis Sentinel 架构,maxmemory 设置为 4GB,发现主节点使用内存 4GB,从节点使用内存 2GB。
排查过程:主节点是否有大批量的写入?查看监控发现没有。
主从不一致?主从都执行 dbsize 命令,发现都是 23254136。
客户端溢出?实际上已经收到报警了,最大输出缓冲区溢出了,这个时候我们完全可以使用 client list 命令找到 omem 为 0 的客户端连接:
redis-cli client list | grep -v "omem=0"
发现有一个 oll=201261 omem=4675586842 cmd=monitor 的连接,根据 cmd==monitor 判断执行来源是 monitor,monitor 拉取了那么大数据,但是自身消费不了,这个时候我们可以将 monitor 直接干掉,进行内存回收。
预防策略:
- 运维层面:线上 Redis 禁用 monitor(rename-command)命令;适度限制缓冲区大小;
- 开发层面:理解 monitor 原理,也可以短暂寻找热点 key(本地执行);使用 CacheCloud 可以直接监控到。
3、其他方法
- 不要忽视 key 的长度,1 亿个键,1 个字节也是节省;
- 序列化和压缩方法,拒绝 java 原生,采用 protobuf、keyo、snappy 等。
最后
以上就是强健蜜粉为你收集整理的Redis 性能调优——内存优化1.内存消耗2.缓冲内存3.对象内存4.内存管理5.内存优化的全部内容,希望文章能够帮你解决Redis 性能调优——内存优化1.内存消耗2.缓冲内存3.对象内存4.内存管理5.内存优化所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复