快看,我们的分布式缓存就是这样把注册中心搞崩塌

写公众号两年以来,每当有机会写故障类主题的时候,我都会在开始前静静地望着显示器很久,经过多次煎熬和挣扎之后才敢提起笔来,为什么呢?因为这样的话题很容易招来吐槽,比如 “说了半天,不就是配置没配好吗?”,或者 “这代码是猪写的吗?你们团队有懂性能测试的同学吗?”,这样的评论略带挑衅,而且充满了鄙视之意。

不过我觉得,在技术的世界里,多数情况都是客观场景决定了主观结果,而主观结果又反映了客观场景,把场景与结果串起来,用自己的方式写下来,传播出去,与有相同经历的同学聊上一聊,也未尝不是一件好事。

上个月,我们的系统因注册中心崩塌而引发的一场事故,本是一件稀松平常的事件,可我们猜中了开始却没料到原因,始作俑者竟是已在产线运行多年的某分布式缓存系统。

这到底是怎么一回事呢?

先来回顾一下故障过程

11月,某交易日的上午10点左右。

在中间件监控系统没有触发任何报警的情况下,某应用团队负责人突然跑过来说:“怎么缓存响应怎么慢?你们在干什么事吗?”

由于此正在交易盘中,中间件运维团队瞬间炸锅,紧急查看了一系列监控数据,先是通过Zabbix查看了如CPU、内存、网络及磁盘等基础预警,一切正常,再查看服务健康状况,经过一圈折腾之后,也没发现任何疑点。

懵圈了,没道理啊。

10点30分,收到一通报警信息,内容为 “ZK集群中的某一个节点故障,端口不通,不能获取node信息,请迅速处理!”。

这简单,ZK服务端口不通,重启,立即恢复。

10点40分,ZK集群全部瘫痪,无法获取Node数据,由于应用系统的Dubbo服务与分布式缓存使用的是同一套ZK集群,而且在此期间应用未重启过,因此应用服务自身暂时未受到影响。

没道理啊,无论应用侧还是缓存侧,近一个月以来都没有发布过版本,而且分布式缓存除了在ZK中存一些节点相关信息之外,基本对ZK无依赖。

10点50分,ZK集群全部重启,10分钟后,再次瘫痪。

神奇了,到底哪里出了问题呢?

10点55分,ZK集群全部重启,1分钟后,发现Node Count达到近22W+,再次崩溃。

10点58分,通过增加监控脚本,查明Node源头来自分布式缓存系统的本地缓存服务

11点00分,通过控制台关闭本地缓存服务后,ZK集群第三次重启,通过脚本删除本地化缓存所产生的大量node信息。

11点05分,产线ZK集群全部恢复,无异常。

一场风波虽说过去了,但每个人的脸上流露出茫然的表情,邪了门了,这本地缓存为什么能把注册中心搞崩塌?都上线一年多了,之前为什么不出问题?为什么偏偏今天出事?

一堆的问好,充斥着每个人的大脑。

我们本地缓存的工作机制

去年,我曾经在 #好买的分布式缓存中间件# 的内容中对我们的分布式缓存做过相对详细的说明,所以在这里,我就通过系统流程示意图的方式,简要的说明下我们本地缓存系统的一些核心工作机制。

| 非本地缓存的工作机制

本地缓存的工作机制 – KEY预加载/更新

| 本地缓存的工作机制 – Set/Delete操作

| 本地缓存的工作机制 – Get操作

顺带提一句,由于历史性与资源紧缺的原因,我们部分缓存系统与应用系统的ZK集群是混用的,正因如此,给本次事故埋下了隐患。

ZK集群是怎样被搞挂的呢?

说到这里,相信对中间件有一定了解的人基本能猜出本事件的全貌。

简单来说,就是在上线初期,由于流量小,应用系统接入量小,我们本地缓存的消息通知是利用ZK来实现的,而且还用到了广播。但随着流量的增加与应用系统接入量的增多,消息发送量成倍增长,最终达到承载能力的上限,ZK集群崩溃。

的确,原因基本猜对了,但消息发送量为什么会成倍的增长呢?

根据本地缓存的工作机制,我们一般会在里面存些什么呢?

  1. 更新频率较低,但访问却很频繁,比如系统参数或业务参数。
  2. 单个Key/Value较大,网络消耗比较大,性能下降明显。
  3. 服务端资源匮乏或不稳定(如I/O),但对稳定性要求极高。

懵圈了,就放些参数类信息,而且更新频率极低,这样就把五个节点的ZK集群发爆了?

为了找到真相,我们立即进行了代码走读,最终发现了蹊跷。

根据设计,在 “本地缓存的工作机制 – Set/Delete操作” 的工作机制中,当一个Key完成服务端缓存操作后,如果没有被加到本地缓存规则列表中的KEY,是不可能被触发消息通知的,但这里明显存在BUG,导致把所有的KEY都发到了ZK中。

这样就很好理解了,虽然应用系统近期没有发布版本,但却通过缓存控制台,悄悄地把分布式锁加到了这套缓存分片中,所以交易一开盘,只需几十分钟,立马打爆。

另外,除了发现BUG之外,通过事后测试验证,我们还得出了以下几点结论:

  1. 利用ZK进行消息同步,ZK本身的负载能力较弱,是否切换到MQ?
  2. 监控手段的单一,监控的薄弱;
  3. 系统部署结构不合理,基础架构的ZK不应该与应用的ZK混用;

说到这里,这个故事也该结束了。

讲在最后

看完这个故事,一些爱好怼人的小伙伴也许会忍不住发问。你们自己设计的架构,你们自己编写的代码,难道不知道其中的逻辑吗?这么低级的错误,居然还有脸拿出来说?

那可未必,对每个技术团队而言,核心成员的离职与业务形态的变化,都或多或少会引发技术团队对现有系统形成 “知其然而,却不知其所以然” 的情况,虽说每个团队都在想方设法进行避免,但想完全杜绝,绝非易事。

作为技术管理者,具备良好的心态,把每次故障都看成是一次蝉变的过程,从中得到总结与经验,并加以传承,今后不再就犯,那就是好样的。

不过,万一哪天失手,给系统来了个彻底瘫痪,该怎么办呢?

祝大家一切顺利吧。

Image placeholder
IT头条
未设置
  16人点赞

没有讨论,发表一下自己的看法吧

推荐文章
Dubbo 稳定性案例:Nacos 注册中心可用性问题复盘

问题描述上周四晚刚回到家,就接到了软负载同学的电话,说是客户线上出了故障,我一听”故障“两个字,立马追问是什么情况,经过整理,还原出线上问题的原貌:客户使用了Dubbo,注册中心使用的是Nacos,在

滴滴 曾奇:谈谈我所认识的分布式锁

桔妹导读:随着计算机技术和工程架构的发展,微服务变得越来越热。如今,绝大多数服务都处于分布式环境中,其中,数据一致性是我们一直关注的重点。分布式锁到底是什么?经过了哪些发展演进?工程上有哪些实现方案?

10分钟搞懂:亿级用户的分布式数据存储解决方案!

来源:IT进阶思维原创,转载请注明原出处内容提供:李智慧,前阿里巴巴技术专家,《大型网站技术架构》作者6月6日晚,林志玲与Akira公布婚讯、徐蔡坤祝福高考同学超常发挥,粉丝们百万的转发和点赞造成微博

一个简单的基于 Redis 的分布式任务调度器 —— Java 语言实现

折腾了一周的JavaQuartz集群任务调度,很遗憾没能搞定,网上的相关文章也少得可怜,在多节点(多进程)环境下Quartz似乎无法动态增减任务,恼火。无奈之下自己撸了一个简单的任务调度器,结果只花了

干货 | 揭秘京东数科强一致、高性能的分布式事务中间件JDTX

导读:在分布式数据库、云原生数据库、NewSQL等名词在数据库领域层出不穷的当今,变革——在这个相对稳定的领域已愈加不可避免。相比于完全革新,渐进式增强的方案在拥有厚重沉淀的行业则更受青睐。同所有分布

基于 Zookeeper 的分布式锁实现

1.背景最近在学习Zookeeper,在刚开始接触Zookeeper的时候,完全不知道Zookeeper有什么用。且很多资料都是将Zookeeper描述成一个“类Unix/Linux文件系统”的中间件

如何设计缓存系统:缓存穿透,缓存击穿,缓存雪崩解决方案分析

前言设计一个缓存系统,不得不要考虑的问题就是:缓存穿透、缓存击穿与失效时的雪崩效应。缓存穿透缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则

使用Jenkins一键打包部署SpringBoot应用,就是这么6!

SpringBoot实战电商项目mall(25k+star)地址:https://github.com/macrozheng/mall 摘要任何简单操作的背后,都有一套相当复杂的机制。本文将以Spri

历史上最著名计算机病毒,似乎都成了我们的回忆

Windows勒索病毒似乎让全球计算机用户都闻风丧胆,不过这其实真的不算什么。然而令人始料不及的是,即便勒索病毒传遍了100多个国家,也仅仅才收获了5万美金。所以说勒索病毒真的不算啥。历史上比勒索病毒

是什么能让 APP 快速精准定位到我们的位置?

本文作者:smallyang,腾讯IEG开发工程师什么是geohash?它的原理是什么?它帮助我们解决了哪些痛点,本文为你娓娓道来。本文包含以下内容,阅读完需要约10分钟:我们日常生活中遇到哪些定位的

漫画 |《程序员十二时辰》,居然是这样的!内容过于真实 …

作者:纯洁的微笑漫画:法小四据说程序员的一天是这样渡过….7:00开始新的一天起床缓冲中,已经进行……6%回想昨晚不该又High到2点7:10闹钟响到第6次的时候,终于鼓起勇气起床。其实我也不想那么晚

Go语言高级编程_6.1 分布式id生成器

6.1分布式id生成器 有时我们需要能够生成类似MySQL自增ID这样不断增大,同时又不会重复的id。以支持业务中的高并发场景。比较典型的,电商促销时,短时间内会有大量的订单涌入到系统,比如每秒10w

Go语言高级编程_6.2 分布式锁

6.2分布式锁 在单机程序并发或并行修改全局变量时,需要对修改行为加锁以创造临界区。为什么需要加锁呢?我们看看在不加锁的情况下并发计数会发生什么情况: packagemain import( "sy

Go语言高级编程_6.4 分布式搜索引擎

6.4分布式搜索引擎 在Web一章中,我们提到MySQL很脆弱。数据库系统本身要保证实时和强一致性,所以其功能设计上都是为了满足这种一致性需求。比如writeaheadlog的设计,基于B+树实现的索

Go语言高级编程_6.6 分布式配置管理

6.6分布式配置管理 在分布式系统中,常困扰我们的还有上线问题。虽然目前有一些优雅重启方案,但实际应用中可能受限于我们系统内部的运行情况而没有办法做到真正的“优雅”。比如我们为了对去下游的流量进行限制

Go语言高级编程_6.7 分布式爬虫

6.7分布式爬虫 互联网时代的信息爆炸是很多人倍感头痛的问题,应接不暇的新闻、信息、视频,无孔不入地侵占着我们的碎片时间。但另一方面,在我们真正需要数据的时候,却感觉数据并不是那么容易获取的。比如我们

分布式Redis深度历险-复制

摘要Redis深度历险分为两个部分,单机Redis和分布式Redis。本文为分布式Redis深度历险系列的第一篇,主要内容为Redis的复制功能。Redis的复制功能的作用和大多数分布式存储系统一样,

从关系型数据库到分布式机器学习,揭秘腾讯大数据十年发展历程

大数据技术在过去10多年中极大改变了企业对数据的存储、处理和分析方式。如今,大数据技术逐渐成熟,涵盖了计算、存储、数仓、数据集成、可视化、NOSQL、OLAP分析、机器学习等丰富领域。在未来,大数据技

云原生时代,分布式系统设计必备知识图谱(内含22个知识点)

作者|杨泽强(竹涧)阿里云技术专家我们身处于一个充斥着分布式系统解决方案的计算机时代,无论是支付宝、微信这样顶级流量产品、还是区块链、IOT等热门概念、抑或如火如荼的容器生态技术如Kubernetes

中国移动智能硬件质量报告解读 分布式路由市场你了解多少?

今年6月份,中国移动终端实验室发布了《中国移动2019年智能硬件质量报告》(第一期),并于近日对该报告进行了相关解读,同时对优秀智能硬件产品进行颁奖。根据介绍,本次报告在内容上主要包括手机产品综合评测

分布式时序数据库QTSDB的设计与实现

现有的开源时序数据库influxdb只支持单机运行,在面临大量数据写入时,会出现查询慢,机器负载高,单机容量的限制。为了解决这一问题,360基础架构团队在单机influxdb的基础上,开发了集群版——

为什么分布式网络是一种新兴趋势?

互联网的大规模采用可归功于以下五个重要因素:TCP/IPTCP/IP(传输控制协议/Internet协议)是指Internet上使用的标准数据通信协议集。它由DARPA开发,并由互联网工程任务组(IE

分布式存储时代,横空出世的OceanBase

数据,被誉为新时代的石油。几乎任何一个企业的IT管理者,都会在演讲、采访或其他形式的交流分享中强调数据的重要性。获取洞察、行为预测、市场分析、业务转型升级……数据能够为企业带来巨大的商业价值。但与此同

深入浅出百亿请求高可用Redis(codis)分布式集群揭秘

摘要:作为noSql中的kv数据库的王者,redis以其高性能,低时延,丰富的数据结构备受开发者青睐,但是由于redis在水平伸缩性上受限,如何做到能够水平扩容,同时对业务无侵入性是很多使用redis

分布式事务实战

引言:微服务倡导将复杂的单体应用拆分为若干个功能简单、松耦合的服务,这样可以降低开发难度、增强扩展性、便于敏捷开发,从而被越来越多的开发者和公司推崇运用。但系统微服务化后,一个看似简单的功能,内部可能