Redis内存占用异常排查
当内存超出负载时,PHP 连接 Redis 时出现报错信息:
LOADING Redis is loading the dataset in memory
或者RedisException: read error on connection to
。通常情况下某个 Redis 节点内存占用异常无外乎 2个 原因,存在碎片或存在特别大的 Key。
# Redis查看内存情况
登录Redis服务端,查看内存使用情况。
[root@redis01 bin]# ./redis-cli
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> info momory
127.0.0.1:6379>
[root@redis01 bin]# ./redis-cli
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> info memory
# Memory
used_memory:853256
used_memory_human:833.26K
used_memory_rss:7835648
used_memory_rss_human:7.47M
used_memory_peak:853256
used_memory_peak_human:833.26K
used_memory_peak_perc:100.01%
used_memory_overhead:841030
used_memory_startup:791336
used_memory_dataset:12226
used_memory_dataset_perc:19.74%
allocator_allocated:889680
allocator_active:1167360
allocator_resident:3674112
total_system_memory:1019568128
total_system_memory_human:972.34M
used_memory_lua:37888
used_memory_lua_human:37.00K
used_memory_scripts:0
used_memory_scripts_human:0B
number_of_cached_scripts:0
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
allocator_frag_ratio:1.31
allocator_frag_bytes:277680
allocator_rss_ratio:3.15
allocator_rss_bytes:2506752
rss_overhead_ratio:2.13
rss_overhead_bytes:4161536
mem_fragmentation_ratio:9.65
mem_fragmentation_bytes:7023408
mem_not_counted_for_evict:0
mem_replication_backlog:0
mem_clients_slaves:0
mem_clients_normal:49694
mem_aof_buffer:0
mem_allocator:jemalloc-5.1.0
active_defrag_running:0
lazyfree_pending_objects:0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# info memory参数详解
指标 | 含义 |
---|---|
used_memory | 由Redis分配器分配的内存总量,包含了redis进程内部的开销和数据占用的内存,以字节(byte)为单位,即当前redis使用内存大小。 |
used_memory_human | 已更直观的单位展示分配的内存总量。 |
used_memory_rss | 向操作系统申请的内存大小,与 top 、 ps等命令的输出一致,即redis使用的物理内存大小。 |
used_memory_rss_human | 已更直观的单位展示向操作系统申请的内存大小。 |
used_memory_peak | redis的内存消耗峰值(以字节为单位),即历史使用记录中redis使用内存峰值。 |
used_memory_peak_human | 以更直观的格式返回redis的内存消耗峰值 |
used_memory_peak_perc | 使用内存达到峰值内存的百分比,used_memory/ used_memory_peak) 100%,即当前redis使用内存/历史使用记录中redis使用内存峰值100% |
used_memory_overhead | Redis为了维护数据集的内部机制所需的内存开销,包括所有客户端输出缓冲区、查询缓冲区、AOF重写缓冲区和主从复制的backlog。 |
used_memory_startup | Redis服务器启动时消耗的内存 |
used_memory_dataset | 数据实际占用的内存大小,即used_memory-used_memory_overhead |
used_memory_dataset_perc | 数据占用的内存大小的百分比,100%*(used_memory_dataset/(used_memory-used_memory_startup)) |
total_system_memory | 整个系统内存 |
total_system_memory_human | 以更直观的格式显示整个系统内存 |
used_memory_lua | Lua脚本存储占用的内存 |
used_memory_lua_human | 以更直观的格式显示Lua脚本存储占用的内存 |
maxmemory | Redis实例的最大内存配置 |
maxmemory_human | 以更直观的格式显示Redis实例的最大内存配置 |
maxmemory_policy | 当达到maxmemory时的淘汰策略 |
mem_fragmentation_ratio | 碎片率,used_memory_rss/ used_memory。ratio指数>1表明有内存碎片,越大表明越多,<1表明正在使用虚拟内存,虚拟内存其实就是硬盘,性能比内存低得多,这是应该增强机器的内存以提高性能。一般来说,mem_fragmentation_ratio的数值在1 ~ 1.5之间是比较健康的。详解 |
mem_allocator | 内存分配器 |
active_defrag_running | 表示没有活动的defrag任务正在运行,1表示有活动的defrag任务正在运行(defrag:表示内存碎片整理)详解 |
lazyfree_pending_objects | 0表示不存在延迟释放的挂起对象 |
# 碎片清理功能
1、自动清理:默认情况下自动清理碎片的参数是关闭的,可以按如下命令查看。
127.0.0.1:6379> config get activedefrag
1) "activedefrag"
2) "no"
1
2
3
2
3
2、启动自动清理内存碎片
127.0.0.1:6379> config set activedefrag yes
OK
1
2
2
3、手动清理
127.0.0.1:6379> memory purge
OK
1
2
2
# 查看是否存在大Key
线上 Redis 存储占用异常,某些机器内存资源异常,查看内存信息 mem_fragmentation_ratio
为 1.03。
根据经验怀疑是某些较大的 Key 占用了内存而没有释放。需要找出 Redis 中占用内存资源较大的 Key。
[root@redis01 bin]# ./redis-cli -h 127.0.0.1 -a 123456 -p 6379 --bigkeys
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
# Scanning the entire keyspace to find biggest keys as well as
# average sizes per key type. You can use -i 0.1 to sleep 0.1 sec
# per 100 SCAN commands (not usually needed).
-------- summary -------
Sampled 0 keys in the keyspace!
Total key length in bytes is 0 (avg len 0.00)
0 hashs with 0 fields (00.00% of keys, avg size 0.00)
0 lists with 0 items (00.00% of keys, avg size 0.00)
0 strings with 0 bytes (00.00% of keys, avg size 0.00)
0 streams with 0 entries (00.00% of keys, avg size 0.00)
0 sets with 0 members (00.00% of keys, avg size 0.00)
0 zsets with 0 members (00.00% of keys, avg size 0.00)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 导出指定Key
./redis-cli -h 127.0.0.1 -a 密码 get 'xxx' > xx.txt
1
# 删除指定Key
127.0.0.1:6379> del key [key ...]
1
# Redis的淘汰机制
在 Redis 中,允许用户设置最大使用内存大小 maxmemory(需要配合 maxmemory-policy 使用),设置为 0 表示不限制;当 Redis 内存数据集快到达 maxmemory 时,Redis 会实行数据淘汰策略。
Redis提供6种数据淘汰策略:
策略 | 说明 |
---|---|
volatile-lru | 从已设置过期时间的内存数据集中挑选最近最少使用的数据淘汰 |
volatile-ttl | 从已设置过期时间的内存数据集中挑选即将过期的数据淘汰 |
volatile-random | 从已设置过期时间的内存数据集中任意挑选数据淘汰 |
allkeys-lru | 从内存数据集中挑选最近最少使用的数据淘汰 |
allkeys-random | 从数据集中任意挑选数据淘汰 |
no-enviction | 禁止驱逐数据。(默认淘汰策略,当redis内存数据达到maxmemory,在该策略下,直接返回OOM错误); 关于maxmemory设置,通过在redis.conf中maxmemory参数设置,或者通过命令CONFIG SET动态修改。 关于数据淘汰策略的设置,通过在redis.conf中的maxmemory-policy参数设置,或者通过命令CONFIG SET动态修改。 |
上次更新: 2023/09/05, 16:08:13