写点什么

探测准确度90%以上,小米工程师的HDFS慢节点监控与处理技术实践

2020 年 11 月 25 日

探测准确度90%以上,小米工程师的HDFS慢节点监控与处理技术实践

HDFS(Hadoop 分布式文件系统)集群随着使用时间的增长,难免会出现一些“性能退化”的节点,主要表现为磁盘读写变慢、网络传输变慢,我们统称这些节点为慢节点。当集群扩大到一定规模,比如上千个节点的集群,慢节点通常是不容易被发现的。大多数时候,慢节点都藏匿于众多健康节点中,只有在客户端频繁访问这些有问题的节点,发现读写变慢了,才会被感知到。


因此,要想维护 HDFS 集群读写性能稳定,慢节点问题一直是一个绕不开的话题。在 Hadoop2.9 之后,社区支持了从 Namenode jmx 上查看慢节点的功能,小米基于此框架,开发了一整套 HDFS 集群慢节点监控及自动处理流程,在实际生产环境中,具有不错的应用效果,可以保证慢节点能够被及时准确发现,并在 NameNode 端自动规避处理。

1、HDFS 写 pipeline 的流程


为了保证高可靠性,文件默认以三副本的形式保存在 HDFS 上,当 client 开始写入一个新文件的时候,首先会找出三个 DataNode 建立 pipeline,随后数据以 packet 为最小单元,依次通过 pipeline 里的三个 DN,完成三副本写入。


具体的写入流程是:首先 DN0 收到从 client 端传过来的 packet,DN0 立即将 packet 传至下游 DN,随后对 packet 进行落盘操作,DN1 的操作与 DN0 一致,DN2 作为 pipeline 里的最后一个节点,在落盘数据之后,会向上游 DN 发送 ack,DN1 在收到 ack 后继续向上游转发,DN0 在收到 DN1 的 ack 后向 client 端转发,client 收到 DN0 的 ack 即完成一次完整的 pipeline 写入流程。



HDFS 写 pipeline 流程


在写 pipeline 的过程中,如果出现了网络慢节点,步骤 1 的耗时会明显增加,如果出现的是磁盘慢节点,步骤 2 的耗时会明显增加,因此,HDFS 的慢节点监控,主要是监控步骤 1 和步骤 2 的耗时。

2、网络慢监控原理


2.1 收集数据


监控一个 DN 网络传输变慢的原理是,记录集群里各个 DN 间的数据传输耗时,找出其中的异常值并作为慢节点上报给 NN。正常情况下各节点间的传输速率基本一致,不会相差太多,假如出现了 A 传 B 耗时异常,A 就往 NN 上报 B 是慢节点,NN 端在汇总所有慢节点报告后,会判断是否存在慢节点。比如 X 节点是故障节点,那么一定会有很多节点往 NN 上报 X 是慢节点,最终在 NN 端出现类似的慢节点报告,表明 X 是慢节点。



为了计算 DN 往下游传数据的平均耗时,DN 内部维护了一个 HashMap<String,Queue<SampleStat>>,HashMap 的 key 为下游 DN 的 ip,value 是一个存放 SampleStat 对象的队列。SampleStat 对象用于记录往下游 DN 传输 packet 的数量与总耗时,DN 默认每五分钟做一次 snapshot,生成一个 SampleStat,用于记录在这五分钟内,往下游 DN 传输数据的网络情况,并存入 HashMap 的 Queue。


HashMap 的 Queue 是一个固定大小的队列,队列长度 36,如果队列满了,就会踢掉队首成员把新的 SampleStat 加入队尾。这意味着,我们只会监控最近 3 小时(36 X 5=180min)的网络传输情况,目的是为了保证监控数据具有时效性。



收集监控数据


这样,我们就可以知道 DN1 往集群其他 DN 传数据的耗时情况,如果存在慢节点,数据从 DN1 传到它的耗时一定会比其他线路高很多。


这里还要考虑到几个场景,一个是如果在最近五分钟内,DN1 没有往 DN2 传输数据,那 SampleStat 里的数据应该取什么?答案是直接复用上一个五分钟的数据,因为我们不能说在这五分钟没有数据传输,网络就是没有问题的,有很大的可能,它的网络状况和前一个五分钟是一致的,所以在没有数据传输的情况下,直接复用上一周期的数据是合理的。


更进一步的,如果超过 3 个小时 DN1 都没有往 DN2 传数据,HashMap 对应的 Queue 将会出现 36 个一样的 SampleStat,那么基于 Queue 生成的慢节点报告将不具备时效性。因此我们需要在 DN 做 snapshot 的时候,给 SampleStat 带上一个时间戳,保证我们只监控最近 3 个小时的数据。


还有一个问题是,pipeline 里有三个 DN,DN 间有两段网络传输,这两段网络传输我们都需要关注吗?其实我们只需要关注最后一段,即 DN1 往 DN2 传数据的情况就可以。一个是为了精简统计量,另一个原因是,第一段网络传输(DN0 到 DN1)在其他 pipeline 里可能就是最后一段,所以从整体上看只要监控最后一段的传输延迟,可以保证集群所有 DN 都能被监控到。


2.2 发送慢节点报告


DN 在上报心跳的时候会判断是否需要生成 SlowPeerReport,并将其作为心跳信息的一部分发送给 NN。SlowPeerReport 的生成周期与 DN 做 snapshot 生成 SampleStat 的周期一致,默认取五分钟。首先从 Queue 取出所有 SampleStat 做叠加,求算数平均值 averageLatency,那么在最近三小时,DN1 往 DN2 传数据的平均延迟就是 averageLatency1_2。然后根据这些 averageLatency,算出慢节点上报阈 upperLimitLatency。当有节点的 averageLatency 大于 upperLimitLatency,即认为该节点属于一个网络慢节点,且由 DN1 上报。最后生成对应的 SlowPeerReport,通过心跳上报给 NN。



DN 发送慢节点报告


对于 upperLimitLatency 的计算,我们先算出 averageLatency 的中位数 median,并以此算出中位数绝对偏差 MAD(Median absolute deviation)[1]。MAD 是一个健壮的统计量,比标准差σ更能适应数据集中场景的异常值,也就是说少量的异常值不会影响最终结果。


MAD=median(∣Xi−median(X)∣)


通常认为 median + 3 x MAD 是异常值,出现的概率是千分之几,这一点类似于正态分布的 3σ定律[2]。



正态分布 3σ准则


因此慢节点上报阈值 upperLimitLatency 可以取 median + 3 x MAD,但是我们也要考虑到集群的容忍度,设定一个固定的 lowThreshold,取两者间的较大值为 upperLimitLatency。


2.3 监控


NN 内部维护一个慢节点 HashMap<String,List<ReportingNode>,用于汇总慢节点信息。它的 key 是慢节点 IP,value 是对应的上报节点。NN 在收到心跳后,从慢节点报告中解析出慢节点 slowNode 及其对应上报节点 reportingNode,更新至 HashMap。reportingNode 会记录心跳的上报时间,用于判断所上报的慢节点报告是否具有时效性,一般取 DN 上报慢节点周期间隔的 3 倍为慢节点报告有效期,即 5*3=15min。


慢节点报警通过使用一个独立的探测程序 Canary 实现,Canary 会定期查询 NN jmx,触发 getSlowPeersReport 方法,遍历 HashMap 查询是否存在 slowNode。


为了解决报警恢复的问题,我们通过修改 DN 心跳协议,在慢节点报告中增加当前五分钟传输延迟 currentLatency。基于此,报警触发以及恢复的标准如下:


  • currentLatency > threshold,触发报警

  • currentLatency > 0 && currentLatency < threshold,网络状况已恢复,报警OK

  • currentLatency = 0.0 && averageLatency > threshold,最近五分钟没有数据传输,但三个小时内平均网络延迟很高,极有可能网络传输依然很慢,报警继续

3、磁盘慢监控原理



坏盘的间歇性卡顿


正常情况下对 hdfs 写入来说,各个盘的写入量是差不多的,如果进入写入高峰期,那就是整个节点所有盘的写入速度都明显变慢,没有异常值,这种情况是不会报磁盘慢的。但如果出现特殊情况,只有个别盘突然进入一个短暂高峰期,它的写延迟将明显上涨,直接判断这是一个慢磁盘显然是不合理的,因此慢节点探测需要规避掉这类场景。



高峰流量造成短暂卡顿


为了提高探测准确率,我们决定采用计数的方式来判断这个磁盘是否真正出了问题。每 5 分钟做一次统计,如果在一个小时内,出现了 6 次以上的写入慢,可以认为这是一块有问题的磁盘,将生成 SlowDiskReport 报告给 NN。



采用计数的方式判断慢盘


具体的实现方式是,每个盘都维护一个长度为 12 的 Queue,每 5 分钟尝试更新一次 Queue,如果盘的 WriteIo 平均值大于 upperLimitLatency,就将此刻 timestamp 加入 Queue,表示在这一周期出现了写入磁盘慢,如果 Queue 满了就把队首成员踢掉再入列。在生成 SlowDiskReport 的时候,如果队列是满的且队首成员的 timestamp 在一个小时以内,就意味着,在最近一个小时,磁盘写慢的时间超过了 30 分钟,该磁盘将会被加入 SlowDiskReport 上报给 NN。


4、NameNode 自动处理慢节点


我们进一步扩展了慢节点监控的功能,在 NN 端维护一个 HashMap,用来记录已经上报的慢节点。这样 NN 在选 DN 建立 pipeline 的时候,可以尽量规避掉这些存在问题的节点。NN 周期性查询慢节点报告,当发现新的慢节点信息,就更新 HashMap,它的 key 为节点 ip,value 是慢节点信息过期时间 expire time,expire time=current+ interval,用来表明这个节点在 expire time 之前会标识为慢的状态。


NN 在选 DN 的时候,如果选中了慢节点,就加入 exclude 列表,重新选一次,最终选到正常节点建立 pipeline。但是这里也要考虑集群中正常节点数不够的情况,如果遍历完所有可用节点,依然选不到 DN 会抛 NotEnoughReplicasException,此时将触发重新选择,这一轮的选择不会考虑慢节点场景,这样可以保证 NN 在选 DN 的时候尽量不会选到慢节点。



NameNode 自动处理慢节点


5、总结


整个慢节点监控的流程如下图所示:



慢节点监控及自动处理流程


该功能目前已经上线小米规模最大的离线集群,探测的准确度在 90%以上,已累计为集群找出上百块坏盘。NN 自动处理慢节点极大节省了人工介入成本,SRE 只需要每周进行一次故障节点处理,即可保证集群读写性能稳定。

参考资料

[1]中位数绝对偏差 MAD:https://en.wikipedia.org/wiki/Median_absolute_deviation

[2]正态分布:https://en.wikipedia.org/wiki/Normal_distribution


备注:本文首发于小米技术,经授权转载。

原文链接:https://mp.weixin.qq.com/s/wP8MlQr6Q-Z542YzpBCZEA


2020 年 11 月 25 日 14:38799

评论 2 条评论

发布
用户头像
图都看不到,也没有原始地址
2020 年 11 月 25 日 17:22
回复
图片现在可以看到了,原文链接请参考:https://mp.weixin.qq.com/s/wP8MlQr6Q-Z542YzpBCZEA
2020 年 11 月 26 日 13:17
回复
没有更多了
发现更多内容

程序员陪娃漫画系列——修龙头

孙苏勇

生活 程序员人生 陪伴 漫画

Disruptor为何这么快

Rayjun

Java Disruptor

终极 Shell

池建强

Linux Shell

「超级右键」

非著名程序员

macos 程序员 效率工具 软件 Mac

敏捷开发 | 张三与需求管理

Worktile

敏捷开发 需求管理

漫谈哲学与编程

keelii

编程 哲学

随手记备忘录的好习惯

changyou

加班能解决交付的期望么?

拖地先生

项目管理 领导力 管理 时间管理

在谈判中,你有哪些属于自己的独特的方法和技巧?

Yolanda

敏捷(组织)转型的6个准备条件

Bob Jiang

团队管理 敏捷 组织转型

浅谈负载均衡

Damon

Java 负载均衡 Kubernetes 微服务架构 Spring Cloud

Facebook在用户增长到5亿时的扩容策略

Rayjun

团队管理 扩容

写作平台使用感受

小天同学

产品 体验 反馈

最近的一些人生感悟

小智

人生 哲学

知乎开发了一个搜索引擎

红泥小壶

搜索引擎 百度 知乎

很不幸,自动化测试永远只能是必要非充分条件

刘华Kenneth

DevOps 敏捷 自动化 测试 金字塔

克制文章长度

changyou

聊聊苹果公司技术部门的宫斗和冷战

赵钰莹

程序员 外包 apple

我敢说 80% 的程序员都掉进了「老鼠赛跑」的陷阱

非著名程序员

读书笔记 程序员 程序人生 提升认知

理性主义和实证主义

王泰

理性主义 实证主义 哲学 软件工程

软件工程的史前时代 -- Therac-25 事件

王泰

质量管理 软件工程 软件危机 软件测试

小论互联网项目管理

南方

项目管理 互联网 个人成长 碧海潮生曲

如何阅读源码?

武培轩

Java 源码 面试 进阶 后端

揭秘|为何程序员们能一直保持高收入?

丁长老

学习 程序员 写作 高薪

软件世界中的个人英雄与团队协作

王泰

团队管理 软件工程 团队协作

Zoom的加密算法,到底有什么问题?

范学雷

算法 编码习惯 产品设计 安全 编程语言

Java并发编程系列——线程

孙苏勇

Java 并发编程 线程

回"疫"录(2):不知者无畏

小天同学

疫情 回忆录 现实纪录

有关Kotlin Companion 我们需要了解到的几个知识点

王泰

Java 编程 kotlin 编程语言

死磕Java并发编程(6):从源码分析清楚AQS

七哥爱编程

Java Java并发 并发编程 AQS

基于Kubernetes的多云和混合云

倪朋飞

云计算 架构 Kubernetes 微服务架构 Service Mesh

2021年,算法还“香”吗?

2021年,算法还“香”吗?

探测准确度90%以上,小米工程师的HDFS慢节点监控与处理技术实践-InfoQ