随笔 - 23  文章 - 2 评论 - 2 阅读 - 51545
< 2025年3月 >
23 24 25 26 27 28 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 1 2 3 4 5

最近生产环境遇到一个很奇怪的问题,系统内存32G,redis使用8G左右,剩余的内存都被系统cache使用,从表面上看系统可用内存有20G左右。但是系统运行过程中,redis时不时会用到swap,而且在AOF重写期间swap使用量更是突增(mem_fragmentation_ratio 值低于1)导致redis性能严重下降。

然后搜索网上的各种资料,调整redis参数,主要做了以下几个部分:

1、调整/ proc/sys/vm/swappiness

2、调整 no-appendfsync-on-rewrite yes,减少AOF重写时的IO争用

3、添加最大内存限制 maxmemory 24gb

4、手动释放cache echo 1 > /proc/sys/vm/drop_caches,释放后系统过一段时间又会占满

以上操作完成后,仍然没有效果。

然后采取临时手段,在备机上将swap分区禁用,暂时解决问题,主机仍然保留现场继续查问题(这期间调整auto-aof-rewrite-percentage 300,减少重写频率)。

最后查看到关于NUMA的资料,结合生成环境系统分析,确认存在内存分配策略问题的这种可能性。

大概的原因如下:

在多核CPU的环境下,numa采用对CPU和内存分组的方式管理资源,每个CPU分组对应1个内存分组,在默认策略情况下,CPU使用自己组内的内存空间,若新进程申请内存时,没有足够的空闲内存,则可能用到swap空间,而不去其他CPU组申请内存。

这里有一个简单的验证方法:

1、手工释放cache echo 1 > /proc/sys/vm/drop_caches

2、numactl --hardware  查看每个CPU分组中空余内存大小是否基本一致,若出现某个组free很小,其他组明显大于该组,则可能是内存策略分配引起的问题。

注意:这里看到的free是不含cache部分占用的内存,所以要先释放一下cache

解决办法:

在redis启动命令前面加上 numactl --interleave=all ,表示采用轮询的方式到各组申请内存,这样重启redis后问题解决,改善的点如下:

1、redis AOF重写时不再使用到swap,重写基本在1分钟左右完成(故障期间长达30分钟)

2、sar -b 查看IO,每秒写入量和tps均有明细下降

3、redis内存碎片指数 mem_fragmentation_ratio 一直保持大于1

NUMA参考资料http://www.cnblogs.com/xueqiuqiu/articles/9282903.html

posted on   lzc_jack  阅读(952)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
点击右上角即可分享
微信分享提示