当前位置:首页 > 问答 > 正文

云Redis终于找到定位卡死的根源,解决了困扰多时的问题,性能提升明显

(根据阿里云开发者社区2023年9月发布的故障复盘文章《一次罕见的云数据库Redis卡顿排查之旅》整理)

我们用的云Redis曾经遇到一个怪事,平时好好的,但时不时就会突然卡住几秒钟,整个服务就像冻住了一样,监控大图上看,CPU、网络流量都正常,就是操作响应时间会突然飙高,然后自己又恢复,这个问题像幽灵一样,隔三差五出现一次,查了很久都没头绪,特别头疼。

云Redis终于找到定位卡死的根源,解决了困扰多时的问题,性能提升明显

一开始,我们和云厂商的工程师怀疑过网络问题,查了虚拟网络、宿主机,没发现异常,也怀疑过是不是Redis本身命令太复杂或者有慢查询,但日志里也排除了,甚至想过是不是隔壁邻居太吵,被其他租户影响了,结果监控显示宿主机的资源也很空闲。

后来,一位工程师决定盯住Redis实例的详细监控指标,一直盯着看,突然在一次卡顿发生的瞬间,他捕捉到了一个关键变化:“Used Memory”(Redis自己统计的内存使用量)没怎么变,但“RSS”(进程实际占用的物理内存)指标瞬间涨了一大截,卡顿结束后又落回去了,就是这个细微的差别,成了破案的关键线索。

云Redis终于找到定位卡死的根源,解决了困扰多时的问题,性能提升明显

顺着这个线往下挖,技术团队发现,根本原因出在内存分配器上,Redis默认用的内存分配器是jemalloc,它管理内存就像管理很多个不同大小的格子,当应用频繁申请和释放不同大小的内存时,就会产生很多内存碎片,这些碎片就像行李箱里散乱的小物件,它们加起来占着地方(导致RSS很高),但没法拼出一个完整的大空间给Redis用(所以Used Memory显示不高),平时相安无事,但当Redis需要申请一块连续大内存时,分配器就得花大力气去整理、合并这些碎片,这个整理过程就会导致Redis主线程完全卡住,什么请求都处理不了,这就是我们感受到的那几秒“冻住”的时刻。

问题根源锁定后,解决起来就有了方向,云厂商的技术团队没有简单地建议我们升级实例规格,而是从底层做了优化,他们调整了jemalloc的配置参数,让它在后台更积极、更平缓地进行碎片整理,避免碎片积压到一定程度再突然进行大规模整理,也优化了内核与内存分配器之间的协作机制。

(根据同一文章后续更新)优化上线后,我们这边观察了很长一段时间,那个恼人的、毫无规律的周期性卡顿再也没有出现过,以前在业务高峰时总是提心吊胆,现在服务平稳多了,最直观的感受就是,之前超时报警里那些偶发的Redis错误几乎消失了,服务的整体响应速度也变得更加稳定,这次经历让我们意识到,有些深层次的问题,藏在那些最基础的、平时不太关注的监控指标里。

备用