1、内存不足,性能急剧下降
在内存不足的情况下,操作系统会启用swap机制,这个时候,Redis主线程会导致大量磁盘IO,极大的增加Redis响应时间,导致Redis性能急剧下降。
为此,我们除了要给Redis服务设置最大内存之外,还需要监控Redis服务器的内存使用情况,避免与其他内存需求大的应用一起运行。
如何监控swap情况
1 | # 找到Redis的进程号,进入/proc目录,进行查看 |
如果发现很多几百MB或者上GB的swap,就说明实例的内存压力很大,需要排查是否内存不足导致Redis性能变慢。
2、内存大页机制
在发起BGSAVE命令之后,Redis会fork出一个子进程用于执行生成RDB文件。fork的时候采用的是写时复制(Copy-on-write)技术。不会立刻复制所有的内存,只是复制了页表,保证了fork执行足够快。
如果此时正好开启了内存大页机制,即使客户端请求的数据只有几k,也会拷贝2MB的大页,最终导致大量的内存拷贝,从而影响Redis的访问速度。
为了避免这种情况,可以关闭内存大页机制:
1 | [root@VM_0_14_centos ~]# echo never > /sys/kernel/mm/transparent_hugepage/enabled |
3、碎片
Redis并没有实现自己的内存池,也没有基于标准的系统内存分配器进行扩展。因此,系统内存分配器的性能和碎片率会对Redis产生一定的性能影响。向jemalloc这类的分配策略,是以一系列固定大小来进行内存空间的划分的,如8bit、16bit、32bit…这无形之中会导致一些分配的内存用不上,导致内存碎片的出现。
而内存碎片的出现,会导致内存空间利用率不高,导致无法分配新的空间。
如,在Redis中,SDS的空间预分配策略就很容易造成内存碎片。另外,频繁的删改操作、键值对大小不一致,也是造成内存碎片的原因之一。
为了监控Redis是否存在内存碎片,可以执行以下命令:
1 | 127.0.0.1:6379> INFO memory |
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 | # 启用主动碎片整理 |
您可以在不用重启Redis的情况下,通过以下方式启用碎片整理:
1 | redis-cli config set activedefrag "yes" |