一、背景介绍
Redis作为互联网业务首选的远程缓存工具而被被大家熟知和使用,在客户端方面涌现了Jedis、Redisson、Lettuce等,而Jedis属于其中的佼佼者。
目前笔者的项目采用Redis的3.x版本部署的集群模式(多节点且每个节点存在主从节点),使用Jedis作为Redis的访问客户端。
日前Redis集群中的某节点因为宿主物理机故障导致发生主从切换,在主从切换过程中触发了Jedis的重试机制进而引发了服务的雪崩。
本文旨在剖析Redis集群模式下节点发生主从切换进而引起服务雪崩的整个过程,希望能够帮助读者规避此类问题。
二、故障现场记录
消息堆积告警
【MQ-消息堆积告警】
- 告警时间:2022-11-29 23:50:21
- 检测规则: 消息堆积阈值:-》异常( >100000)
- 告警服务:xxx-anti-addiction
- 告警集群:北京公共
- 告警对象:xxx-login-event-exchange
/xxx-login-event-queue - 异常对象(当前值):159412
说明:
- 2022-11-29 23:50:21收到一条RMQ消息堆积的告警,正常情况下服务是不会有这类异常告警,出于警觉性开始进入系统排查过程。
- 排查的思路基本围绕系统相关的指标:系统的请求量,响应时间,下游服务的响应时间,线程数等指标。
说明:
排查系统监控之后发现在故障发生时段服务整体的请求量有大幅下跌,响应的接口的平均耗时接近1分钟。
服务整体出于雪崩状态,请求耗时暴涨导致服务不可用,进而导致请求量下跌。
说明:
排查服务的下游应用发现故障期间Redis的访问量大幅下跌,已趋近于0。
项目中较长用的Redis的响应耗时基本上在2s。
说明:
排查系统对应的线程数,发现在故障期间处于wait的线程数大量增加。
说明:
事后运维同学反馈在故障时间点Redis集群发生了主从切换,整体时间和故障时间较吻合。
综合各方面的指标信息,判定此次服务的雪崩主要原因应该是Redis主从切换导致,但是引发服务雪崩原因需要进一步的分析。
三、故障过程分析
在进行故障的过程分析之前,首先需要对目前的现象进行分析,需要回答下面几个问题:
- 接口响应耗时增加为何会引起请求量的陡增?
- Redis主从切换期间大部分的耗时为啥是2s?
- 接口的平均响应时间为啥接近60s?
3.1 流量陡降
说明:
通过nginx的日志可以看出存在大量的connection timed out的报错,可以归因为由于后端服务的响应时间过程导致nginx层和下游服务之间的读取超时。
由于大量的读取超时导致nginx判断为后端的服务不可用,进而触发了no live upstreams的报错,ng无法转发到合适的后端服务。
通过nginx的日志可以将问题归因到后端服务异常导致整体请求量下跌。
3.2 耗时问题
说明:
通过报错日志定位到Jedis在获取连接的过程中抛出了connect timed out的异常。
通过定位Jedis的源码发现默认的设置连接超时时间 DEFAULT_TIMEOUT = 2000。
<redis-cluster name="redisCluster" timeout="3000" maxRedirections="6"> // 最大重试次数为6
<properties>
<property name="maxTotal" value="20" />
<property name="maxIdle" value="20" />
<property name="minIdle" value="2" />
</properties>
</redis-cluster>