字节跳动 EB 级 HDFS 实践(1)

因为 HDFS 这样一个系统已经存在了非常长的时间,应用的场景已经非常成熟了,所以这部分我们会比较简单地介绍。

HDFS 全名 Hadoop Distributed File System,是业界使用最广泛的开源分布式文件系统。原理和架构与 Google 的 GFS 基本一致。它的特点主要有以下几项:

  • 和本地文件系统一样的目录树视图

  • Append Only 的写入(不支持随机写)

  • 顺序和随机读

  • 超大数据规模

  • 易扩展,容错率高

字节跳动特色的 HDFS

============

字节跳动应用 HDFS 已经非常长的时间了,经历了 7 年的发展,目前已直接支持了十多种数据平台,间接支持了上百种业务发展。从集群规模和数据量来说,HDFS 平台在公司内部已经成长为总数几万台服务器的大平台,支持了 EB 级别的数据量。

在深入相关的技术细节之前,我们先看看字节跳动的 HDFS 架构。

架构介绍


接入层

接入层是区别于社区版本最大的一层,社区版本中并无这一层定义。在字节跳动的落地实践中,由于集群的节点过于庞大,我们需要非常多的 NameNode 实现联邦机制来接入不同上层业务的数据服务。但当 NameNode 数量也变得非常多了以后,用户请求的统一接入及统一视图的管理也会有很大的问题。为了解决用户接入过于分散,我们需要一个独立的接入层来支持用户请求的统一接入,转发路由;同时也能结合业务提供用户权限和流量控制能力;另外,该接入层也需要提供对外的目录树统一视图。

该接入层从部署形态上来讲,依赖于一些外部组件如 Redis,MySQL 等,会有一批无状态的 NNProxy 组成,他们提供了请求路由,Quota 限制,Tracing 能力及流量限速等能力。

元数据层

这一层主要模块有 Name Node,ZKFC,和 BookKeeper(不同于 QJM,BookKeeper 在大规模多节点数据同步上来讲会表现得更稳定可靠)。

Name Node 负责存储整个 HDFS 集群的元数据信息,是整个系统的大脑。一旦故障,整个集群都会陷入不可用状态。因此 Name Node 有一套基于 ZKFC 的主从热备的高可用方案。

Name Node 还面临着扩展性的问题,单机承载能力始终受限。于是 HDFS 引入了联邦(Federation)机制。一个集群中可以部署多组 Name Node,它们独立维护自己的元数据,共用 Data Node 存储资源。这样,一个 HDFS 集群就可以无限扩展了。但是这种 Federation 机制下,每一组 Name Node 的目录树都互相割裂的。于是又出现了一些解决方案,能够使整个 Federation 集群对外提供一个完整目录树的视图。

数据层

相比元数据层,数据层主要节点是 Data Node。Data Node 负责实际的数据存储和读取。用户文件被切分成块复制成多副本,每个副本都存在不同的 Data Node 上,以达到容错容灾的效果。每个副本在 Data Node 上都以文件的形式存储,元信息在启动时被加载到内存中。

Data Node 会定时向 Name Node 做心跳汇报,并且周期性将自己所存储的副本信息汇报给 Name Node。这个过程对 Federation 中的每个集群都是独立完成的。在心跳汇报的返回结果中,会携带 Name Node 对 Data Node 下发的指令,例如,需要将某个副本拷贝到另外一台 Data Node 或者将某个副本删除等。

主要业务


先来看一下当前在字节跳动 HDFS 承载的主要业务:

  • Hive,HBase,日志服务,Kafka 数据存储

  • Yarn,Flink 的计算框架平台数据

  • Spark,MapReduce 的计算相关数据存储

发展阶段


在字节跳动,随着业务的快速发展,HDFS 的数据量和集群规模快速扩大,原来的 HDFS 的集群从几百台,迅速突破千台和万台的规模。这中间,踩了无数的坑,大的阶段归纳起来会有这样几个阶段。

第一阶段

业务增长初期,集群规模增长趋势非常陡峭,单集群规模很快在元数据服务器 Name Node 侧遇到瓶颈。引入联邦机制(Federation)实现集群的横向扩展。

联邦又带来统一命名空间问题,因此,需要统一视图空间帮助业务构建统一接入。这里我们引入了 Name Node Proxy 组件实现统一视图和多租户管理等功能。为了解决这个问题,我们引入了 Name Node Proxy 组件实现统一视图和多租户管理等功能,这部分会在下文的 NNProxy 章节中介绍。

第二阶段

数据量继续增大,Federation 方式下的目录树管理也存在瓶颈,主要体现在数据量增大后,Java 版本的 GC 变得更加频繁,跨子树迁移节点代价过大,节点启动时间太长等问题。因此我们通过重构的方式,解决了 GC,锁优化,启动加速等问题,将原 Name Node 的服务能力进一步提高。容纳更多的元数据信息。为了解决这个问题,我们也实现了字节跳动特色的 DanceNN 组件,兼容了原有 Java 版本 NameNode 的全部功能基础上,大大增强了稳定性和性能。相关详细介绍会在下面的 DanceNN 章节中介绍。

第三阶段

当数据量跨过 EB,集群规模扩大到几万台的时候,慢节点问题,更细粒度服务分级问题,成本问题和元数据瓶颈进一步凸显。我们在架构上进一步在包括完善多租户体系构建,重构数据节点和元数据分层等方向进一步演进。这部分目前正在进行中,因为优化的点会非常多,本文会给出慢节点优化的落地实践。

关键改进


在整个架构演进的过程中,我们做了非常多的探索和尝试。如上所述,结合之前提到的几个大的挑战和问题,我们就其中关键的 Name Node Proxy 和 Dance Name Node 这两个重点组件做一下介绍,同时,也会介绍一下我们在慢节点方面的优化和改进。

NNProxy(Name Node Proxy)

作为系统的元数据操作接入端,NNProxy 提供了联邦模式下统一元数据视图,解决了用户请求的统一转发,业务流量的统一管控的问题。

先介绍一下 NNProxy 所处的系统上下游。

我们先来看一下 NNProxy 都做了什么工作。

路由管理

在上面 Federation 的介绍中提到,每个集群都维护自己独立的目录树,无法对外提供一个完整的目录树视图。NNProxy 中的路由管理就解决了这个问题。路由管理存储了一张 mount table,表中记录若干条路径到集群的映射关系。

例如 /user -> hdfs://namenodeB,这条映射关系的含义就是 /user 及其子目录这个目录在 namenodeB 这个集群上,所有对 /user 及其子目录的访问都会由 NNProxy 转发给 namenodeB,获取结果后再返回给 Client。

匹配原则为最长匹配,例如我们还有另外一条映射 /user/tiger/dump -> hdfs://namenodeC,那么 /user/tiger/dump 及其所有子目录都在 namenodeC,而 /user 目录下其他子目录都在 namenodeB 上。如下图所示:

Quota 限制

使用过 HDFS 的同学会知道 Quota 这个概念。我们给每个目录集合分配了额定的空间资源,一旦使用超过这个阈值,就会被禁止写入。这个工作就是由 NNProxy 完成的。NNProxy 会通过 Quota 实时监控系统获取最新 Quota 使用情况,当用户进行元数据操作的时候,NNProxy 就会根据用户的 Quota 情况作出判断,决定通过或者拒绝。

Trace 支持

ByteTrace 是一个 Trace 系统,记录追踪用户和系统以及系统之间的调用行为,以达到分析和运维的目的。其中的 Trace 信息会附在向 NNProxy 的请求 RPC 中。NNProxy 拿到 ByteTrace 以后就可以知道当前请求的上游模块,USER 及 Application ID 等信息。NNProxy 一方面将这些信息发到 Kafka 做一些离线分析,一方面实时聚合并打点,以便追溯线上流量。

流量限制

虽然 NNProxy 非常轻量,可以承受很高的 QPS,但是后端的 Name Node 承载能力是有限的。因此突发的大作业造成高 QPS 的读写请求被全量转发到 Name Node 上时,会造成 Name Node 过载,延时变高,甚至出现 OOM,影响集群上所有用户。因此 NNProxy 另一个非常重要的任务就是限流,以保护后端 Name Node。目前限流基于路径+RPC 以及 用户+RPC 维度,例如我们可以限制 /user/tiger/warhouse 路径的 create 请求为 100 QPS,或者某个用户的 delete 请求为 5 QPS。一旦该用户的访问量超过这个阈值,NNProxy 会返回一个可重试异常,Client 收到这个异常后会重试。因此被限流的路径或用户会感觉到访问 HDFS 变慢,但是并不会失败。

Dance NN(Dance Name Node)

解决的问题

如前所述,在数据量上到 EB 级别的场景后,原有的 Java 版本的 Name Node 存在了非常多的线上问题需要解决。以下是在实践过程中我们遇到的一些问题总结:

  • Java 版本 Name Node 采用 Java 语言开发,在 INode 规模上亿时,不可避免的会带来严重的 GC 问题;

  • Java 版本 Name Node 将 INode meta 信息完全放置于内存,10 亿 INode 大约占用 800GB 内存(包含 JVM 自身占用的部分 native memory),更进一步加重了 GC;

  • 我们目前的集群规模下,Name Node 从重启到恢复服务需要 6 个小时,在主备同时发生故障的情况下,严重影响上层业务;

  • Java 版本 Name Node 全局一把读写锁,任何对目录树的修改操作都会阻塞其他的读写操作,并发度较低;

从上可以看出,在大数据量场景下,我们亟需一个新架构版本的 Name Node 来承载我们的海量元数据。除了 C++语言重写来规避 Java 带来的 GC 问题以外,我们还在一些场景下做了特殊的优化。

目录树锁设计

HDFS 对内是一个分布式集群,对外提供的是一个 unified 的文件系统,因此对文件及目录的操作需要像操作 Linux 本地文件系统一样。这就要求 HDFS 满足类似于数据库系统中 ACID 特性一样的原子性,一致性、隔离性和持久性。因此 DanceNN 在面对多个用户同时操作同一个文件或者同一个目录时,需要保证不会破坏掉 ACID 属性,需要对操作做锁保护。

不同于传统的 KV 存储和数据库表结构,DanceNN 上维护的是一棵树状的数据结构,因此单纯的 key 锁或者行锁在 DanceNN 下不适用。而像数据库的表锁或者原生 NN 的做法,对整棵目录树加单独一把锁又会严重的影响整体吞吐和延迟,因此 DanceNN 重新设计了树状锁结构,做到保证 ACID 的情况下,读吞吐能够到 8w,写吞吐能够到 2w,是原生 NN 性能的 10 倍以上。

这里,我们会重新对 RPC 做分类,像 createFilegetFileInfosetXAttr 这类 RPC 依然是简单的对某一个 INode 进行 CURD 操作;像 delete RPC,有可能删除一个文件,也有可能会删除目录,后者会影响整棵子树下的所有文件;像 rename RPC,则是更复杂的另外一类操作,可能会涉及到多个 INode,甚至是多棵子树下的所有 INode。

DanceNN 启动优化

由于我们的 DanceNN 底层元数据实现了本地目录树管理结构,因此我们 DanceNN 的启动优化都是围绕着这样的设计来做的。

多线程扫描和填充 BlockMap

在系统启动过程中,第一步就是读取目录树中保存的信息并且填入 BlockMap 中,类似 Java 版 NN 读取 FSImage 的操作。在具体实现过程中,首先起多个线程并行扫描静态目录树结构。将扫描的结果放入一个加锁的 Buffer 中。当 Buffer 中的元素个数达到设定的数量以后,重新生成一个新的 Buffer 接收请求,并在老 Buffer 上起一个线程将数据填入 BlockMap。

接收块上报优化

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

最后

在这里我和身边一些朋友特意整理了一份快速进阶为Android高级工程师的系统且全面的学习资料。涵盖了Android初级——Android高级架构师进阶必备的一些学习技能。

附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!

资料。涵盖了Android初级——Android高级架构师进阶必备的一些学习技能。**

附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

[外链图片转存中…(img-6sKeNNAd-1712396072563)]

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
  • 24
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值