数据库
首页 > 数据库> > 故障分析| Redis 故障诊断及常用运维命令—内存篇

故障分析| Redis 故障诊断及常用运维命令—内存篇

作者:互联网

作者:任仲禹

爱可生 DBA 团队成员,擅长故障分析和性能优化,文章相关技术问题,欢迎大家一起讨论。

本文来源:原创投稿

*爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。

本文目录:

背景

  • Redis 内存消耗划分

  • 内存 OOM 会导致哪些问题?

排查思路

  • 是否数据量太大?

  • 是否客户端输入缓冲区有问题?

  • 是否复制积压缓冲区有问题?

  • 是否客户端输出缓冲区有问题?

实用命令

  • 模拟 Redis 压力相关命令

  • 常⽤ Redis 内存排查命令

总结

背景

你是否有过这种困扰:我的数据量非常小,但还是报 OOM 错误?

# ⼀个简单set提示内存不⾜
[root@10-186-61-38 redis]# redis-cli -p 9999 set actionsky 1
(error) OOM command not allowed when used memory > 'maxmemory'.

首先我给大家解释下,Redis 的 OOM 分两种。

OOM 是 Redis 最常见的内存故障,它影响很大:

本文中,我会给大家分享下该种内存问题的排查方向及运维命令

Redis 内存消耗划分

简短介绍下 Redis 内存消耗划分情况,为下文诊断提供思路。上图可以总结 Redis 消耗内存分如下几块:

内存 OOM 会导致哪些问题?

1.Redis 无法写入,只能读取。

2.Redis 大量键被逐出内存或过期,导致 Redis 查询效率降低(maxmemory-policy 配置为非默认值 noeviction 时)。

排查思路

注意:下文不做特别说明的话,我的 maxmemory 设置为 1G,其它任何参数为默认。

是否数据量太大?

使用 redis-benchmark 持续灌入数据,

检查内存使用情况,发生 OOM 状态时 used_memory ⼀定会大于 maxmemory。

检查数据对象内存和其它内存使用情况如下图:

这里有必要说明下 overhead.total,它包括除数据外 Redis 消耗的所有内存,比如前面提到的复制缓冲区、客户端输入输出缓冲区等,另外还包括⼀些元数据如 overhead.hashtable,它是数据库中元数据消耗的内存大小,包括以下三项:

大家对这个现象可能有点疑惑,为啥我明明设置 maxmemory 为 1G,你 Redis 只给我存了 990 多 M 数据就满了?

很好理解,根据上面测试可知数据达到⼀定规模后,因需消耗额外的元数据、缓存内存,Redis 最终将超过 maxmemory 而 OOM。

是否客户端输入缓冲区有问题?

制造输入缓冲区压力(防止干扰,先清空数据再压测)

# 关键参数解释
-d 表示每个set值的大小,单位为字节
-c 启多少个连接

压测几秒钟后,触发 OOM,

检查输入缓冲区内存消耗,能看到客户端输入缓冲区消耗总量为 2.4G左右,远远超过 maxmemory 参数设置。

那我如何找到消耗内存量最大的那个连接呢?

可通过运行上述检查命令,定位到各客户端输入缓冲区的内存消耗(由大到小排序)。

⼀般如果定位到有连接异常,可以使用如下命令杀掉。

# 例如杀掉上图中 id=51421 的连接
127.0.0.1:9999> CLIENT KILL ID 51421
(integer) 1

是否复制积压缓冲区有问题?

为测试方便,我直接把复制积压缓冲区配置为 800M。

开启 redis-benchmark 压测进程,

检查复制积压缓冲区内存消耗,可以看到因为缓冲区设置过大,数据量才存储 190 多 M,Redis 就无法写入了。

是否客户端输出缓冲区有问题?

若客户端输出缓冲区太大如何排查?⼀般该场景比较少见,常见于用到了 redis 的 monitor 命令。

注意:monitor 命令功能像 MySQL 的 general-log,能打印 Redis 所有执行的命令。在生产环境极少使用或禁用。

先开启 monitor 命令,

通过 redis-benchmark 制造输出缓冲区压力。

测试⼀段时间后观察 Redis 内存消耗,

此时数据库无法写入,

检查输出缓冲区各客户端连接内存消耗、输出缓冲区总消耗内存如下,

可以看到输出缓冲区总内存已远大于 maxmemory 限制,此时内存⾃然就 OMM。

实用命令

上文排查过程有些 Redis 运维命令我认为比较实用,整理如下:

模拟 Redis 压力相关命令

# 1. 持续给Redis灌数据
redis-benchmark -p 9999 -t set -r 100000000 -l
# 2. 模拟输入缓冲区过大
redis-benchmark -p 9999 -q -c 10 -d 102400000 -n 10000000 -r 50000 -t set
# 3. 模拟输出缓冲区过大
redis-benchmark -p 9999 -t get -r 5000000 -n 10000000 -d 100 -c 1000 -P 500 -l

常用 Redis 内存排查命令

# 1. 快速查看Redis内存是否够用
redis-cli -p 9999 info memory |egrep
'(used_memory_human|maxmemory_human|maxmemory_policy)'
# 2. 检查复制积压缓冲区使用情况
redis-cli -p 9999 memory stats|egrep -A 1
'(total.allocated|replication.backlog)'
# 3. 检查客户端输入缓冲区内存使用总量
redis-cli -p 9999 client list| awk 'BEGIN{sum=0}
{sum+=substr($12,6);sum+=substr($13,11)}END{print sum}'
# 4. 检查客户端输入缓冲区各客户端连接的内存情况
redis-cli -p 9999 client list|awk '{print substr($12,6),$1,$12,$18}'|sort -
nrk1,1 | cut -f1 -d" " --complement
# 5. 检查客户端输出缓冲区内存使用总量
redis-cli -p 9999 client list| awk 'BEGIN{sum=0} {sum+=substr($16,6)}END{print
sum}'
# 6. 检查客户端输出缓冲区各客户端连接的内存使用排序
redis-cli -p 9999 client list|awk '{print substr($16,6),$1,$16,$18}'|sort -
nrk1,1 | cut -f1 -d" " --complement |head -n10
# 7. 检查数据对象使用内存总量
redis-cli -p 9999 memory stats|grep -A 1 'dataset.bytes'

总结

https://www.jianshu.com/p/a508187bc093

脚本执行效果:

标签:9999,运维,redis,Redis,故障诊断,内存,缓冲区,客户端
来源: https://blog.csdn.net/ActionTech/article/details/115749818