【故障公告】取代 memcached 的 redis 出现问题造成网站故障(已解决)
6月19日开始,我们将博客站点的缓存服务器从 memcached 换成了 redis,稳定运行了3天,今天上午访问高峰突然出现问题,在 11:00-12:30 期间影响了网站的正常访问,由此给您带来麻烦,请求谅解。
在故障期间,日志中大量的等待响应超时错误
StackExchange.Redis.RedisTimeoutException: Timeout awaiting response
其中的一个典型日志:
StackExchange.Redis.RedisTimeoutException: Timeout awaiting response (outbound=0KiB, inbound=6697KiB, 2937ms elapsed, timeout is 2000ms), command=GET, next: GET blog_v2_BlogPosts-291733, inst: 0, qu: 0, qs: 31, aw: False, bw: SpinningDown, rs: ReadAsync, ws: Idle, in: 0, in-pipe: 0, out-pipe: 0, serverEndpoint: 192.168.12.28:6379, mc: 1/1/0, mgr: 5 of 10 available, clientName: blog-web-c845b6686-zpl4s(SE.Redis-v2.5.61.22961), PerfCounterHelperkeyHashSlot: 11935, IOCP: (Busy=0,Free=1000,Min=20,Max=1000), WORKER: (Busy=19,Free=32748,Min=50,Max=32767), POOL: (Threads=73,QueuedItems=5,CompletedItems=2170212), v: 2.5.61.22961 (Please take a look at this article for some common client-side issues that can cause timeouts: https://stackexchange.github.io/StackExchange.Redis/Timeouts)
在确认是 redis 引起的故障后,我们立即采取了笨方法,将之前使用 memcached 缓存的部分切换回 memcached,切换后除了个人博客博文列表页面,其他访问都已恢复正常。
个人博客博文列表一级缓存已经切换到 memcached,但二级缓存还在使用 redis,所以依然受 redis 问题影响。
这时,我们重启了 redis,但重启后问题依旧。本来我们以为是并发高触发的问题,但我们的以为错了。我们重新进行了以为,既然不是并发多的原因,那可能是数据多的原因,flushall 清空 redis 中的数据后,很快恢复了正常。
接下来我们会进一步分析问题的原因,优化 redis 的部署,目前是在 k8s 集群上部署的非高可用 redis 集群(3个节点)。
另外,上次的 k8s 集群翻船问题与我们升级 k8s 时没有升级 calico 网络组件有关,后来把网络组件换成了 cilium,本想上 eBPF 拉风一下,结果发现阿里云负载均衡与 eBPF 存在兼容问题,只好暂时作罢。
更新 6月26日 14:32
进一步排查后发现 "Timeout awaiting response" 问题与我们通过连接池使用多个 ConnectionMultiplexer 有关,连接池越大,越容易出现 timeout。通过 StackExchange.Redis 源码中的注释 ConnectionMultiplexer.cs#L22 看了 PipelinesMultiplexers 之后知道单个 ConnectionMultiplexer 能够应对高并发场景,难怪 StackExchange.Redis 一直没有实现连接池。我们使用连接池是受 StackExchange.Redis.Extensions 的影响,现在看来没有必要而且自找麻烦。
知道这个原因后,解决方法很简单,将 PoolSize 设置为1
。取代 memcached 的 redis 服务已重新上线。
PoolSize=1 的疗效昨天已经得到验证,在切换回 memcached 后,个人博客博文列表一级缓存还在使用 redis ,在日志中依然会出现一些 timeout 异常,当时 PoolSize 值是 10,昨天改为 1 之后 timeout 异常就全部消失。