本文作者:徐葳
时间回退到三年前,2018年04月18日凌晨01点40分,一阵急促的手机短信铃声把我从睡梦中直接拉回了现实。
睡眼朦胧的拿到手机看了一眼,立马精神了,手机屏幕上满满一屏的紧急告警短信,仔细看了一遍,全部都是关于Redis和Kafka的监控告警信息。
在这先说一下基本背景,我们团队负责的产品是猎豹移动旗下的一款海外直播平台(Live.me),主要在海外运营,此直播平台常年处于海外直播社交榜单头部地位。
想要学习英语的小伙伴可以行动起来啦~
使用苹果手机的同学注意了,目前Live.me没有在国内上线运营,所以无法直接在AppStore下载。
针对这种线上的产品,在后台势必会有多层监控程序保驾护航,发现数据有异常就需要立刻通知到对应的负责人。
当时我所在的是数据开发组,主要为直播平台提供数据支撑。这里的告警信息是针对Redis中数据异常的告警,提示在一段时间内数据没有变化。这份数据会提供给算法部门作为计算直播平台首页推荐内容的指标。如果一段时间内没有变化,算法那边就无法准确的计算出当前正在热播的直播内容,也就无法在首页进行推荐,此时首页推荐服务会进行降级,首页就无法准备的展示当前热门的直播内容,只能随机选择一部分正在直播的内容,这样会非常影响用户体验。
Redis里面的数据是我们的实时计算程序(后面就叫它为小A吧)写入的,一段时间内数据没有变化也就意味着小A可能有问题了,排查发现小A确实挂掉了,但是针对小A我们也添加的有监控,异常挂掉会尝试重新拉起的,排查此处的日志发现小A确实被多次拉起,但是拉起之后很快又挂掉了。
小A已经稳定运行了几个月了,代码层面出错的可能性不大,基本可以排除,那就很有可能是依赖的组件出现了问题,经过排查日志发现小A无法从Kafka集群中消费数据。
接着进入Kafka集群管理界面中查看,发现Kafka集群的5个节点都在,到服务器中查看发现Kafka集群中的进程也都在,但是此时告警信息却越来越频繁,告警的程序也是越来越多,多位同事反映都收到了各种各样的告警信息,梳理之后源头都指向了Kafka集群。
此时运维同学也介入了,因为针对集群层面的故障还是需要运维同学一起解决,数据开发部门和运维部门远程成立了一个临时攻关小组,负责解决这个紧急突发线上故障。
看来注定是一个无眠之夜了…
由于已经基本确定是Kafka集群的问题,所以进一步查看Kafka集群的管理界面,突然发现一个异常的数据指标,Kafka集群的其中一个节点在最近一段时间内的数据写入量和读取量非常低,正常情况下Kafka集群每个节点每秒钟的数据写入量和读取量基本上在1w~2w条之间,此时发现这个节点的数据写入量和读取量基本快趋向于0了,也就意味着这个节点现在基本上就不提供服务了。
把这个现象马上反馈给运维同学,经过排查发现,这个节点上的Kafka进程确实还在,但是发现磁盘不可读写了,也就是这个节点上的磁盘发生了故障,导致了Kafka进程还在,但是这个Kafka进程却无法提供数据的生产和消费服务。
其实针对Kafka集群而言,如果挂掉一两个节点对整体服务是没有任何影响的,但是现在遇到的问题就是kafka进程(节点)还在,但是却无法对外提供服务,进而把整个Kafka集群都快拖垮了。
为了快速恢复服务,需要先把这台故障的节点手工下线,但是此时又发现了另外一个问题,因为Kafka集群需要依赖于Zookeeper集群,所以之前在部署的时候把Kafka和Zookeeper部署在了相同的机器上,这5台机器上面既部署了Kafka集群,也部署了Zookeeper集群。那么也就意味着Zookeeper集群应该也出现问题了,连到Zookeeper里面发现Zookeeper集群确实也出现了问题,导致了多个节点中数据不一致的现象。
为了尽快恢复故障,此时最快最好的解决方案是在Zookeeper集群内部找到一个相对来说数据最完整的节点,暂时先使用Zookeeper单机的方式,先把Kafka集群恢复到正常状态。
所以临时的解决方案大致是这样的:
经过这几个步骤之后,监控告警信息逐渐减少了,紧绷的神经稍微放松了一点,此时抬头看了一眼外面,天空已经泛白了,手机显示时间早上6:10分,一夜无眠,来不及休息,洗把脸接着去公司处理后续事宜。
到公司之后,运维同事负责将此次磁盘故障信息反馈给AWS(亚马逊云服务器服务商),因为我们的直播产品主要是在海外运营,所以相关的服务器使用的都是AWS的机器。
在等待AWS反馈消息的时间,我们也进行了复盘和反思。
此次故障虽然说是硬件引起的,但是由于我们的集群架构部署不是很合理,导致在中间解决故障的时候浪费了很多时间,没有在第一时间快速解决问题。
之前是单纯从节约成本的角度考虑,Zookeeper只需要为Kafka提供服务,不需要做其他事情,所以没有单独申请机器部署Zookeeper集群,而是和Kafka集群部署在了一起。这种架构,当出现问题的时候,Kafka和Zookeeper会同时都出现问题,会相应的扩大问题的边界,增加解决问题的复杂度。
基于此,我们重新申请了5台4C8G的机器用来单独部署Zookeeper集群,避免再出现类似的问题。
然后选择了一个业务低峰期,将单机Zookeeper中的数据目录同步到了新部署的Zookeeper集群中,实现Zookeeper的数据迁移,在Kafka集群中替换了新部署的Zookeeper集群的地址信息,并且在Kafka集群中也新增加了一台机器,将Kafka集群恢复到了之前的状态。
最后AWS反馈消息确实是磁盘硬件故障导致的问题,但是这种问题出现的概率极低,所以我们相当于中彩票了,针对这种问题他们也无法提前预知,最简单暴力的方式就是开发一个程序定时读写磁盘主动上报数据,如果一段时间之内没有上报数据,可以从业务层面认为机器故障了,然后对应的进行快速故障转移。