【原创】redis单点大热key叠加pipeline导致服务雪崩

摘要:
原因:经过仔细调查,发现app客户端的主页上有一个基于Redis单点列表结构设计的业务组件。代码逻辑为lrange0-1,即列表中的所有数据都被取出到应用层,然后从应用层中随机取出4个数据并返回给客户端显示。原因可以用一句话概括:Redis单点热键叠加流水线命令,导致Redis不可用,进而导致服务逐渐雪崩。

背景问题:

线上系统自某一天,业务慢慢到高峰,首页会逐步卡顿,高峰时甚至异常白屏,且蔓延到其它界面。

原因:

经过焦灼的排查,定位到:

原因是app客户端首页有一个业务组件是基于redis的单点list结构设计的功能,代码逻辑是lrange 0 -1,即拿出list所有数据到应用层

然后在应用层随机取4个返回客户端展示。 这个组件刚上的时候list里只有几个对象,lrange 0 -1,因为对象少,虽是单点也没啥大问题。

但是这个组件很久未运营配置,年底时运营上了这个组件,此时redis的list里有1000多个对象,这个组件又放在首页qps很大;业务层又会用pipeline,

然后就出了问题。

原因一句话总结:redis单点大热key叠加pipeline命令,导致redis不可用进一步引起服务逐步雪崩

具体过程梳理如下:

1.运营将这个很久不用的组件配置在首页,此时这个组件依赖的redis单点list数据结构中有1000多个对象,list空间大小>1M.

2.依赖的redis的数据结构是个单点key, redis是redis-cluster HA模式。

3.这个组件在首页,访问量很大,峰值>1万QPS, 是个热key.

4.异常时,可以观察到:redis-cluster这个节点内存占用很高,线上报大量io-closeWait异常,网络链接大量超时及重连;原因是因为每次要lrange 0 -1全部数据到应用层,

即每次请求要请求1M数据,然后又是单点热key, 导致了redis响应缓冲区溢出;这个redis节点不可用。

用户侧的感知就是,业务谷点首页还能展示,随着到了业务高峰,会感觉逐步卡顿,到后面蔓延到有依赖redis的所有功能都不可用。

5.之所以会蔓延到其它依赖redis的功能,主要是因为我们业务侧有使用较多的redis pipeline命令,当集群中某个机器发起pipeline命令,

然后这个命令中若有一个key也落在了这个异常的redis单点中,会导致这个pipeline命令也阻塞,那么后续其它命令也会跟着阻塞,即蔓延到了其它依赖redis的功能。

6.最终的表象就是:在业务高点,用户进app基本不可用,其它功能极其卡顿也基本不可用。

解决方式:

1.在定位到具体原因之前,运维做了粗暴的干涉,重启了redis,但是重启后问题依旧存在。思考前面引发的原因可知,重启没啥卵用。
2.大家焦头烂额地定位到了问题,然后立马让运营下掉了这个组件,问题迎刃而解,客户端马上恢复。

影响:

造成了实际的资金损失,影响严重,最终被定级为S0故障,流下了痛苦的眼泪。。。

类似异常排查思路:

一般线上临时出问题,单纯的网络异常、pass异常、机器问题等 运维同学是能够立马识别的;
排除这方面的问题,那肯定是由于什么线上变更导致,应该立马与多方确认,回顾下最近的线上变更
比如最近有没有什么功能发布;如果没有,是否有什么配置变更;如果没有,是不是运营有什么线上运营变更;
几条线摸下来,基本能找到问题方向。
祝好运...

免责声明:文章转载自《【原创】redis单点大热key叠加pipeline导致服务雪崩》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇jQuery radio的取值与赋值linux下screen工具的简单使用下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Redis bigkey分析

一 现象 某个业务最近2个月每月1号凌晨0点都有业务高峰,但是业务所使用的 Redis 服务 cpu 负载100% ,无法对外提供服务进而影响整体业务访问。 二 分析 2.1 问题分析 因为该业务使用的是云Redis ,我们通过监控看 CPU,QPS ,带宽。   出现问题时系统的QPS 大约为 1200 左右,但是对应时刻的出口带宽竟然达到500MB...

二、vue响应式对象

Object.defineProperty Object.defineProperty 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象,先来看一下它的语法: Object.defineProperty(obj, prop, descriptor) obj 是要在其上定义属性的对象; prop 是要定义或修改的属性的...

Spring 实现数据隔离

需求 用户数据要同时支持在mysql和redis进行管理、存储。 思路 利用spring的注解,在配置中指定存储类型,启动时识别并选择对应的实现类。 代码 1. 用户管理的接口类 public interfaceIUserManager { booleancreateUser(User user); booleanremoveUser(); ....

Docker网络[6]

推荐: 狂神说Java Docker学习 1. 理解Docker 0 清空所有网络 # 测试 运行一个tomcat $ docker run -d --name tomcat01 tomcat  再启动一个容器tomcat02测试,发现又多了一对网络   1、我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装...

redis maxmemory设置

关于maxmemory的设置,如果redis的应用场景是作为db使用,那不要设置这个选项,因为db是不能容忍丢失数据的。 如果作为cache使用,则可以启用这个选项(其实既然有淘汰策略,那就是cache了。。。) 指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis会先尝试清除已到期或即将到期的Key, #...

d3的常用方法和数据类型

1. 选择集自身属性 1. selection.empty() 选择集是否为空,为空返回true,否则返回false 2. selection.node() 返回第一个非空元素,无则返回null 3. selection.size() 返回选择集中的元素个数 2. 选择集元素属性 1. attr 设置属性 2. classed 设置class 3. sty...