写点什么

字节跳动 10 万节点 HDFS 集群多机房架构演进之路

2021 年 7 月 20 日

字节跳动10万节点HDFS集群多机房架构演进之路

背景

现状

HDFS 全称是 Hadoop Distributed File System,其本身是 Apache Hadoop 项目的一个模块,作为大数据存储的基石提供高吞吐的海量数据存储能力。自从 2006 年 4 月份发布以来,HDFS 目前依然有着非常广泛的应用,以字节跳动为例,随着公司业务的高速发展,目前 HDFS 服务的规模已经到达“双 10”的级别:

  • 单集群节点 10 万台级别

  • 单集群数据量达到 10EB 级别


主要使用场景包括

  • 离线

  • OLAP 查询引擎存储底座,包括 Hive/ClickHouse/Presto 等场景

  • 机器学习离线训练数据

  • 近线

  • ByteMQ

  • 流式任务 Checkpoint


业界很多公司在维护 HDFS 服务时,采用的都是小集群模式,即生产上部署多个隔离独立的 HDFS 集群满足业务的不同需求。字节跳动采用的是横跨多个机房的联邦大集群部署模式,即 HDFS 只有一个集群,这个集群有多个 nameservice,但是底层的 DN 是横跨 A/B/C 3 个机房的 ,由于社区版 HDFS 没有机房感知相关的支持,因此字节跳动 HDFS 团队在这个功能上做了专门的设计和实现,本文会介绍这部分的工作。

动机

业务的迅猛发展和业务场景的多样性给 HDFS 带来了很大的挑战,这里列几个比较有代表性的问题:

  • 如何在容量上满足业务的发展需求

  • 如何满足近线场景对低延迟的需求

  • 如何满足关键业务的机房级别容灾需求

  • 如何高效运维如此超大规模的集群


要回答这些问题需要 HDFS 从多个方向迭代优化,例如 DanceNN 的上线、运维平台的建设等,本文不会介绍字节跳动 HDFS 所有的演进方案,而是聚焦在 HDFS 多机房架构的演进策略上,它直接回答了上面提到的两个问题,即:

  • 如何在容量上满足业务的发展需求:数据如何合理地在多个机房之间存放以便能通过其他机房的资源进行快速扩容?

  • 如何满足关键业务的容灾需求:系统如何满足核心业务机房级别的容灾需求?

社区版架构

字节跳动的 HDFS 技术脱胎于 Apache 社区的 HDFS,为了方便大家理解内部版本的技术发展历程,本小节我们将先了解一下社区 HDFS 的架构。

图(1) Apache 社区 HDFS 架构


从图(1) 可以看出,社区 HDFS 从架构上划分可以分为 3 部分:

  • Client:访问 HDFS 的 client,主要通过 HDFS SDK 和 HDFS 进行交互,HDFS SDK 的实现比较重,很多 IO 处理逻辑都是在 SDK 实现,因此这里单独列为架构的一部分。

  • 元数据管理:即 NameNode,负责集群的元数据管理,包括目录树和数据块的位置信息。为了解决元数据膨胀问题,社区提供了 Federation 的功能,引入了 NameService 的概念,简单地说,每一个 NameService 提供一个 NameSpace,为了保证 NameNode 的高可用,一个 NameService 包含多个 NameNode 节点(一般是 2 个),这些 NameNode 节点以一主多备的模式工作。Federation 功能跟多机房架构并没有必要的关联,因此接下来讨论我们将不会涉及 Federation/NameService 等概念。

  • 数据管理:即 DataNode,负责存放用户的实际数据,前面提到 NameNode 一个功能是管理数据块的位置信息,在具体实现上,NameNode 不会持久化这些块的信息,而是靠 DataNode 主动汇报来维护。


到目前为止,HDFS 集群的多机房架构相关的方案基本都是元数据层完成的,因此接下来我们的讨论将会聚焦在元数据部分。在本文剩余篇幅里,除非特别声明,否则相关术语都是指字节跳动版的 HDFS。

字节版架构

图(2) 字节跳动 HDFS 架构


注:由于 BookKeeper 自身的架构设计,NameNode(DanceNN)实际上是需要通过 ZooKeeper 去发现 BookKeeper 的 endpoint 信息的,这里为了方便理解,没有把这部分通信关系画出来。


对比图(1) 和 图(2), 我们可以发现,字节跳动的 HDFS 依然保留了社区 HDFS 的核心架构,同时也加入了一些特有的功能,包括:

  • DanceNN,即字节跳动用 C++重新实现的 NameNode,协议上基本兼容社区版的 NameNode。除非特别说明,否则后面出现 DanceNN、NameNode 均指代 DanceNN。

  • NNProxy,即 NameNode Proxy,为 Federation 功能提供统一的 Namespace,由于跟多机房架构直接关系不大,这里不再详细展开。

  • BookKeeper, 即 Apache BookKeeper,其作用是跟社区的 JournaNode 是一样的,就是为 Active 和 Standby NameNode 提供一个共享的 editlog 存储方案,这是实现 NameNode 的 HA 方法的基础。


值得一提的是,BookKeeper 本身提供了机房级别的保存配置策略,这是 HDFS 多机房容灾方案的基础,这个特性确保了 HDFS NameNode 提供跨机房容灾能力,后面我们将继续深入讨论。

演进

双机房

前面提到当前 HDFS 的大集群是横跨 A/B/C 的多机房模式,具体的演进顺序是 A -> A,B -> A,B,C ,现在也保持了直接扩展到更多机房的能力。本小节将着重介绍 A -> A,B 的双机房演进过程,后面的多机房架构的设计思想主要还是双机房架构的扩展。

数据放置

图(3) 字节跳动 HDFS 双机房 DataNode 结构


HDFS 双机房数据放置方案在设计上总结起来可以描述如下:

  • A/B 机房的 DN 直接跨机房组成一个双机房集群,向相同的 NameNode 汇报。

  • 每一个文件在写的时候会保证每个机房至少存在一个副本,数据实时写到两个机房。

  • 每个 Client 在读取文件的时候,优先读取本机房的副本,避免产生大量的跨机房读带宽。


这个设计的好处就是存储层对上层应用屏蔽了集群细节,计算资源可以直接无感分配。该设计结合离线数据一写多读的特点,充分考虑跨机房带宽的合理使用。

  • 由于写带宽一般不会有突发,机房间的离线带宽可以支撑同步写的需求,因此数据可以两个机房同步放置至少一个副本。

  • 离线查询容易有大的突发请求,因此需要确保常规状态下没有突发的跨机房读带宽。


在实现上关键是 DanceNN 加入了机房的感知能力,DanceNN 在 client 进行数据操作时加入对机房拓扑的识别,由于 DanceNN 对外的协议没有改动,因此上层应用不需要做感知改动。

容灾设计

前面介绍了双机房架构里数据放置的设计,它解决了容量扩展的问题,但是并没有解决机房级别的容灾问题,尽管 NameNode 以一主多备的形式实现了高可用,但是所有 NameNode 还是放在一个机房,在字节跳动基础架构的容灾体系里,是需要做到机房级别的容灾。由于 HDFS 的数据已经实现了多机房数据副本的同步写入,为了达成容灾的目标,只需要把元数据也演进到双机房架构即可实现机房级别的容灾。前面我们所说的 HDFS 的元数据组件其实包含了两部分,即 NameNode 和 NameNode Proxy(NNProxy),由于 NNProxy 是无状态的转发服务,因此元数据的多机房架构我们只需要关注在 NameNode 设计上。

图(4) 字节跳动 HDFS NameNode 体系


从图(4) 可以看出 NameNode 包含了 3 个关键模块:

  • Apache ZooKeeper,为 Apache BookKeeper 提供元数据服务。

  • Apache BookKeeper,为 NameNode 的高可用方案提供 EditLog 共享存储方案。

  • DanceNN,即字节跳动自研的高性能 NameNode 实现。


这 3 者构成一个分层的单向依赖关系链, DanceNN -> BookKeeper -> ZooKeeper,因此这 3 者可以独立完成双机房的容灾方案,最终在整体上呈现一个双机房容灾的 NameNode 元数据服务。

组件多机房方案
ZooKeeper一个 ZK ensemble 由 5 台 server 组成,这 5 台 server 分布在 3 个机房,分布比例为 A:B:C = 2:2:1
BookKeeper一个 BK cluster 通常由 14 台 server 组成,分布在 2 个机房,分布比例为 1:1
DanceNN一个 NameService 包含 5 个 DanceNN,这个 5 个 DanceNN 分布在 2 个机房,分布比例为 3:2,工作模式为 1 active + 4standby

在实现上,这里面的关键就是 DanceNN 的 editlog 机房写策略,因为 DanceNN 在做主备切换的时候,如果 editlog 没法保持同步,那么服务是不可用的,得益于 BookKeeper 的机房感知的数据放置功能,DanceNN 可以通过这些策略来完成双机房容灾方案。


  • 常态下,editlog 会以 4 个副本存放到 BookKeeper 上,这 4 个副本的机房分布比例为 1:1。

  • 容灾场景下,DanceNN 可以快速切换成单机房模式,editlog 依然以 4 个副本存放,但是存储策略变为单机房存储,历史的 editlog 也能正常消费。

旁路系统

前面已经介绍完了 HDFS 双机房方案的主体设计,但是事实上一个方案的推进落地除了架构上的迭代演进之外,还需要一系列的旁路系统来配合支持,包括:

  • Balancer:需要感知机房放置

  • Mover:需要保证数据的实际放置满足多机房策略

  • 运维系统

  • 在 federation 架构下,多个 nameservice 需要保证切主的效率

  • 运维操作预案:提前预判相关可能的故障,并且能在运维系统上执行

  • 业务的平稳过渡方案,尽可能少地减少对业务干扰


限于篇幅,本文不会对这些展开细节描述,感兴趣的同学可以再交流。

多机房

HDFS 多机房架构是对双机房架构的扩展,其研发直接动机是机房的资源供应短缺问题,例如 2020 年 B 机房几乎就没有资源供应,但是在公司新的主机房 C 却有较为充裕的资源。一开始我们是尝试将 C 机房作为一个独立的集群提供服务,但是发现业务的血缘关系太过复杂,迁移成本太高,因此选择了基于双机房机房扩展到多机房的方法,该方案需要满足这些需求:

  • 合理使用跨机房带宽

  • 兼容已有的双机房方案

  • 迁移成本尽可能小

  • 符合字节跳动的机房级别容灾标准


最终的设计方案为:

  • 数据放置策略支持多机房,同时兼容已有的双机房放置策略

  • NameNode 的容灾方案策略不变,因为在多机房架构下,HDFS 依然只保证一个机房范围的故障容灾


相应的旁路系统也做相应的调整,尽管 HDFS 底层提供了数据放置在多个机房的策略,但是在离线场景中,用户只能选择 2 个机房存放,例如 A/B, B/C,A/B,这个运营上的策略选择是综合考虑了稳定性、带宽使用的合理性以及资源的合理利用之后确定的,核心目标还是保障业务的平稳发展,从后续实践下来看,这个策略是一个非常正确的选择。

结语

根据我们的不完全调研,字节跳动 HDFS 的多机房架构在业界中是有自己独特的路线,这个中原因主要还是公司业务高速发展和机房建设方向在业界中也是独树一帜的,这些因素驱动 HDFS 进行自己独特迭代演进,从结果来看是达到预期,例如 2020 年 C 机房的充分使用,在 B 机房没有资源供应的情况下依然保障了业务的平稳;2021 春晚活动,为近线业务例如 ByteMQ、流式 CheckPoint 等提供了多机房的容灾策略保障。


最后,HDFS 的多机房架构依然在持续迭代,中长期来看,不排除有更多新机房的出现,这些都给 HDFS 多机房架构提出更多的挑战,原来多机房方案的基础条件不再具备,因此 HDFS 团队已经开启相关功能的迭代,敬请期待!


本文转载自:字节跳动技术团队(ID:toutiaotechblog)

原文链接:字节跳动10万节点HDFS集群多机房架构演进之路

2021 年 7 月 20 日 07:00954

评论

发布
暂无评论
发现更多内容

流水账

zack

【Java虚拟机】垃圾收集器与内存分配

烫烫烫个喵啊

Java Java虚拟机

编程能力 —— 寻路问题

wendraw

Java 前端进阶训练营 编程能力

编程能力 —— 解析表达式

wendraw

Java 前端进阶训练营 编程能力

漫画通信:一图看懂通信发展史

阿里云Edge Plus

利用 Python 爬取了 13966 条运维招聘信息,我得出了哪些结论?

JackTian

Python Linux 运维 数据分析 招聘

最大的 String 字符长度是多少?

武培轩

Java 源码 后端 JVM

521我发誓读完本文,再也不会担心Spring配置类问题了

YourBatman

spring springboot @Configuration Spring配置类

肖风:数据要素市场与分布式AI平台

CECBC区块链专委会

刘华:上云还是不上云,这是一个问题

刘华Kenneth

架构 敏捷

Java 后端博客系统文章系统——No2

猿灯塔

亚马逊:让创新科技成为重启世界的新动能

爱极客侠

HTTP/2 总结

guoguo 👻

实验室里的AI激情:腾讯优图的升级修炼之路

脑极体

微服务架构下分布式事务解决方案

Arthur

16种设计思想 - Design for failure

Man

Java 微服务 设计原则

终于有人把Elasticsearch架构原理讲明白了,感觉之前看的都是渣

爱嘤嘤嘤斯坦

Java elasticsearch 编程 架构

创业使人成长系列 (2)- 散伙协议

石云升

创业 股权 合伙人 散伙协议

积极支持EdgeX发展,英特尔为2020 EdgeX中国挑战赛获奖队伍创造广阔合作空间

最新动态

Docker基础修炼3--Docker容器及常用命令

黑马腾云

Docker Linux 命令 容器技术

区块链+高考,让世界再无冒名顶替

CECBC区块链专委会

Git 常用操作汇总-cheat sheet

多选参数

git GitHub gitlab gitee

计算机操作系统基础(十七)---进程同步之Unix域套接字

书旅

php laravel 线程 操作系统 进程

SpringBoot入门:01 - 配置数据源

封不羁

Java spring springboot

一个爱不释手的Apifox,让我扔掉 Postman的想法

给你买橘子

Java 编程 程序员 开发 Postman

图解:深度优先搜索与广度优先搜索

淡蓝色

Java 数据结构 算法

如果你想写自己的Benchmark框架

程序那些事

JVM 性能调优 GC benchmark

DDD实施过程中的点滴思考

Winfield

领域驱动设计 DDD

5分钟上手部署!!!

清风

Java Spring Boot

【写作群星榜】6.27~7.10 写作平台优秀作者 & 文章排名

InfoQ写作平台官方

写作平台 排行榜

啃碎并发(八):深入分析wait&notify原理 猿码架构

猿灯塔

技术为帆,纵横四海- Lazada技术东南亚探索和成长之旅

技术为帆,纵横四海- Lazada技术东南亚探索和成长之旅

字节跳动10万节点HDFS集群多机房架构演进之路-InfoQ