Redis

洞悉Redis技术内幕:缓存,数据结构,并发,集群与算法
帅旋
关注
充电
IT宅站长,技术博主,共享单车手,全网id:arthinking。

内存引发的Redis性能问题

发布于 2021-06-16 | 更新于 2024-03-03

1、内存不足,性能急剧下降

在内存不足的情况下,操作系统会启用swap机制,这个时候,Redis主线程会导致大量磁盘IO,极大的增加Redis响应时间,导致Redis性能急剧下降。

为此,我们除了要给Redis服务设置最大内存之外,还需要监控Redis服务器的内存使用情况,避免与其他内存需求大的应用一起运行。

如何监控swap情况

1
2
3
# 找到Redis的进程号,进入/proc目录,进行查看
cd /proc/进程号
cat smaps | egrep '^(Swap|Size)'

如果发现很多几百MB或者上GB的swap,就说明实例的内存压力很大,需要排查是否内存不足导致Redis性能变慢。

2、内存大页机制

在发起BGSAVE命令之后,Redis会fork出一个子进程用于执行生成RDB文件。fork的时候采用的是写时复制(Copy-on-write)技术。不会立刻复制所有的内存,只是复制了页表,保证了fork执行足够快

如果此时正好开启了内存大页机制,即使客户端请求的数据只有几k,也会拷贝2MB的大页,最终导致大量的内存拷贝,从而影响Redis的访问速度。

为了避免这种情况,可以关闭内存大页机制:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@VM_0_14_centos ~]# echo never > /sys/kernel/mm/transparent_hugepage/enabled 
[root@VM_0_14_centos ~]# echo never > /sys/kernel/mm/transparent_hugepage/defrag
[root@VM_0_14_centos ~]# cat /sys/kernel/mm/transparent_hugepage/defrag
[always] madvise never
[root@VM_0_14_centos ~]# cat /sys/kernel/mm/transparent_hugepage/enabled
[always] madvise never
# 验证是否生效
[root@VM_0_14_centos ~]# grep Huge /proc/meminfo
AnonHugePages: 18432 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
[root@VM_0_14_centos ~]# cat /proc/sys/vm/nr_hugepages
0

3、碎片

Redis并没有实现自己的内存池,也没有基于标准的系统内存分配器进行扩展。因此,系统内存分配器的性能和碎片率会对Redis产生一定的性能影响。向jemalloc这类的分配策略,是以一系列固定大小来进行内存空间的划分的,如8bit、16bit、32bit…这无形之中会导致一些分配的内存用不上,导致内存碎片的出现。

而内存碎片的出现,会导致内存空间利用率不高,导致无法分配新的空间。

如,在Redis中,SDS的空间预分配策略就很容易造成内存碎片。另外,频繁的删改操作、键值对大小不一致,也是造成内存碎片的原因之一。

为了监控Redis是否存在内存碎片,可以执行以下命令:

1
2
3
4
127.0.0.1:6379> INFO memory
...
mem_fragmentation_ratio:2.64
...

2.64,这个值大不大呢?

这个值的计算公式:

mem_fragmentation_ratio = used_memory_rss/ used_memory

used_memory_rss:操作系统分配给Redis实例的内存大小,表示Redis进程占用的物理内存大小;

used_memory:Redis使用其分配器分配的内存大小;

mem_fragmentation_ratio < 1 表示Redis内存分配超出了物理内存,操作系统正在进行内存交换;

mem_fragmentation_ratio > 1 合理的指标值;

mem_fragmentation_ratio > 1.5 表示Redis消耗了实际需要物理内存的150%以上,其中50%是内存碎片率。

如果这个值超过1.5(50%)了,说明碎片化还是比较严重的,需要进行优化了。

内存碎片清理方法

在Redis 4.0之前,解决内存碎片问题的唯一方法就是重启Redis了,从Redis 4.0开始,提供了主动内存碎片整理的方式。

通过以下配置,来让Redis触发自动内存清理:

1
2
3
4
5
6
7
8
9
10
# 启用主动碎片整理
activedefrag yes
# 启动活动碎片整理的最小碎片浪费量
active-defrag-ignore-bytes 100mb
# 启动活动碎片整理的最小碎片百分比
active-defrag-threshold-lower 10
# 主动碎片整理所用CPU时间最小占比,保证能够正常展开清理
active-defrag-cycle-min 25
# 主动碎片整理所用CPU时间最大占比,超过这个值,就停止清理,避免因为清理导致阻塞Redis
active-defrag-cycle-max 75

您可以在不用重启Redis的情况下,通过以下方式启用碎片整理:

1
redis-cli config set activedefrag "yes"

References

本文作者: 帅旋

本文链接: https://www.itzhai.com/columns/redis/memory-induced-performance-issues.html

版权声明: 版权归作者所有,未经许可不得转载,侵权必究!联系作者请加公众号。

×
IT宅

关注公众号及时获取网站内容更新。