简短介绍下 Redis 内存消耗划分情况,为下文诊断提供思路。上图可以总结 Redis 消耗内存分如下几块:
对象内存:理论上占用最大,存储所有业务数据,如字符串类型、哈希类型对象等。
客户端内存:包括输入客户端(查询或写入命令)、输出客户端使用的内存,因为不受 maxmemory 参数
控制,这块我们需重点排查。
复制积压缓冲:所有从库客户端共享、保存固定大小的写入命令用于从库失连后数据补偿。
Redis 自身内存:存储数据元数据信息、过期键字典等。
AOF 缓冲区:AOF 持久化、重写缓冲区,般占用很少,基本不需要关注。
内存 OOM 会导致哪些问题?
1. Redis 无法写入,只能读取。
2. Redis 大量键被逐出内存或过期,导致 Redis 查询效率降低(maxmemory-policy 配置为非默认值
noeviction 时)。
排查思路
注意:下文不做特别说明的话,我的 maxmemory 设置为 1G,其它任何参数为默认。
是否数据量太大?
使用 redis-benchmark 持续灌入数据,
检查内存使用情况,发生 OOM 状态时 used_memory 定会大于 maxmemory。
检查数据对象内存和其它内存使用情况如下图:
这里有必要说明下 overhead.total,它包括除数据外 Redis 消耗的所有内存,比如前面提到的复制缓冲区、客
户端输入输出缓冲区等,另外还包括些元数据如 overhead.hashtable,它是数据库中元数据消耗的内存大
小,包括以下三项:
整个数据库是种 hash 表,首先就是这张 hash 表使用的内存。
每个 key-value 对都有个 dictEntry 来记录他们的关系,元信息便包含该 db 中所有 dictEntry 使用的
内存。
redis 使用 redisObject 来描述 value 所对应的不同数据类型(string、list、hash、set、zset),那么
redisObject 占用的空间也计算在元数据。
大家对这个现象可能有点疑惑,为啥我明明设置 maxmemory 为 1G,你 Redis 只给我存了 990 多 M 数据
就满了?
评论