字节跳动:10 万节点 HDFS 集群多机房架构演进之路
HDFS 全称是 Hadoop Distributed File System,其本身是 Apache Hadoop 项目的一个模块,作为大数据存储的基石提供高吞吐的海量数据存储能力。自从 2006 年 4 月份发布以来,HDFS 目前依然有着非常广泛的应用,以字节跳动为例,随着公司业务的高速发展,目前 HDFS 服务的规模已经到达 “双 10” 的级别:
- 单集群节点 10 万台级别
- 单集群数据量达到 10 EB 级别
主要使用场景包括
- 离线
- OLAP 查询引擎存储底座,包括 Hive/ClickHouse/Presto 等场景
- 机器学习离线训练数据
- 近线
- ByteMQ
- 流式任务 Checkpoint
业界很多公司在维护 HDFS 服务时,采用的都是小集群模式,即生产上部署多个隔离独立的 HDFS 集群满足业务的不同需求。字节跳动采用的是横跨多个机房的联邦大集群部署模式,即 HDFS 只有一个集群,这个集群有多个 NameService,但是底层的 DN 是横跨 A/B/C 3 个机房的 ,由于社区版 HDFS 没有机房感知相关的支持,因此字节跳动 HDFS 团队在这个功能上做了专门的设计和实现,本文会介绍这部分的工作。
动机
业务的迅猛发展和业务场景的多样性给 HDFS 带来了很大的挑战,这里列几个比较有代表性的问题:
- 如何在容量上满足业务的发展需求
- 如何满足近线场景对低延迟的需求
- 如何满足关键业务的机房级别容灾需求
- 如何高效运维如此超大规模的集群
要回答这些问题需要 HDFS 从多个方向迭代优化,例如 DanceNN 的上线、运维平台的建设等,本文将会聚焦在 HDFS 多机房架构的演进策略上,它直接回答了上面提到的两个问题,即:
- 如何在容量上满足业务的发展需求:数据如何合理地在多个机房之间存放以便能通过其他机房的资源进行快速扩容?
- 如何满足关键业务的容灾需求:系统如何满足核心业务机房级别的容灾需求?
社区版架构
字节跳动的 HDFS 技术脱胎于社区版 HDFS,为了方便大家理解内部版本的技术发展历程,本小节我们将先了解一下社区 HDFS 的架构。
图 (1) 社区版 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 提供跨机房容灾能力,后面我们将继续深入讨论。