世界最优秀的分布式文件系统架构演进之路

简介: 世界最优秀的分布式文件系统架构演进之路

孙玄:毕业于浙江大学,现任转转公司首席架构师,技术委员会主席,大中后台技术负责人(交易平台、基础服务、智能客服、基础架构、智能运维、数据库、安全、IT 等方向);前58集团技术委员会主席,高级系统架构师;前百度资深研发工程师;


【架构之美】微信公众号作者;擅长系统架构设计,大数据,运维、机器学习等技术领域;代表公司多次在业界顶级技术大会 CIO 峰会、Artificial、Intelligence、Conference、A2M、QCon、ArchSummit、SACC、SDCC、CCTC、DTCC、Top100、Strata+、Hadoop World、WOT、GITC、GIAC、TID等发表演讲,并为《程序员》杂志撰稿 2 篇。

一、前言

Hadoop 是一个由 Apache 基金会所开发的分布式系统基础架构。用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储。

Hadoop 实现了一个分布式文件系统(Hadoop Distributed File System),简称HDFS,解决了海量数据存储的问题;实现了一个分布式计算引擎 MapReduce,解决了海量数据如何计算的问题;实现了一个分布式资源调度框架 YARN,解决了资源调度,任务管理的问题。而我们今天重点给大家介绍的是 Hadoop 里享誉世界的优秀的分布式文件系统-HDFS。

Hadoop 重要的比较大的版本有:Hadoop1,Hadoop2,hadoop3。同时也相对应的有 HDFS1,HDFS2,HDFS3 三个大版本。后面的 HDFS 的版本,都是对前一个版本的架构进行了调整优化,而在这个调整优化的过程当中都是解决上一个版本的架构缺陷,然而这些低版本的架构缺陷也是我们在平时工作当中会经常遇到的问题,所以这篇文章一个重要的目的就是通过给大家介绍HDFS 不同版本的架构演进,通过学习高版本是如何解决低版本的架构问题从而来提升我们的系统架构能力。

二、HDFS1

最早出来投入商业使用的的 Hadoop 版本,我们称为 Hadoop1,里面的 HDFS 就是 HDFS1,当时刚出来 HDFS1,大家都很兴奋,因为它解决了一个海量数据如何存储的问题。HDFS1 用的是主从式架构,主节点只有一个叫:Namenode,从节点有多个叫:DataNode。

我们往 HDFS 上上传一个大文件,HDFS 会自动把文件划分成为大小固定的数据块(HDFS1 的时候,默认块的大小是 64M,可以配置),然后这些数据块会分散到存储的不同的服务器上面,为了保证数据安全,HDFS1 里默认每个数据块都有3 个副本。Namenode 是 HDFS 的主节点,里面维护了文件系统的目录树,存储了文件系统的元数据信息,用户上传文件,下载文件等操作都必须跟 NameNode 进行交互,因为它存储了元数据信息,Namenode 为了能快速响应用户的操作,启动的时候就把元数据信息加载到了内存里面。DataNode 是 HDFS 的从节点,干的活就很简单,就是存储 block 文件块。

HDFS1 架构缺陷

缺陷一:单点故障问题(高可用)

我们很清楚的看到,HDFS1 里面只有一个 NameNode,那么也就是说如果这个Namenode 出问题以后,整个分布式文件系统就不能用了。

缺陷二:内存受限问题

NameNode 为了能快速响应用户的操作,把文件系统的元数据信息加载到了内存里面,那么如果一个集群里面存储的文件较多,产生的元数据量也很大,大到namenode 所在的服务器撑不下去了,那么文件系统的寿命也就到尽头了,所以从这个角度说,之前的 HDFS1 的架构里 Namenode 有内存受限的问题。

我们大体能看得出来,在 HDFS1 架构设计中,DataNode 是没有明显的问题的,主要的问题是在 NameNode 这儿。

三、HDFS2

HDFS1 明显感觉架构不太成熟,所以 HDFS2 就是对 HDFS1 的问题进行解决。

01、单点故障问题解决(高可用)

大家先跟着我的思路走,现在我们要解决的是一个单点的问题,其实解决的思路很简单,因为之前是只有一个 NameNode,所以有单点故障问题,那我们把设计成两个 Namenode 就可以了,如果其中一个namenode有问题,就切换到另外一个 NameNode 上。

所以现在我们想要实现的是:其中一个 Namenode 有问题,然后可以把服务切换到另外一个 Namenode 上。如果是这样的话,首先需要解决一个问题:如何保证两个 NameNode 之间的元数据保持一致?因为只有这样才能保证服务切换以后还能正常干活。

保证两个 NameNode 之间元数据一致。

为了解决两个 NameNode 之间元数据一致的问题,引入了第三方的一个 JournalNode 集群。

JournalNode 集群的特点:JournalNode 守护进程是相对轻量级的,那么这些守护进程可与其它 Hadoop 守护进程,如 NameNode,运行在相同的主机上。由于元数据的改变必须写入大多数(一半以上)JNs,所以至少存在 3 个 JournalNodes 守护进程,这样系统能够容忍单个 Journal Node 故障。当然也可以运行多于 3 个JournalNodes,但为了增加系统能够容忍的故障主机的数量,应该运行奇数个JNs。当运行 N 个 JNs 时,系统最多可以接受 (N-1) / 2 个主机故障并能继续正常运行,所以 Jounal Node 集群本身是没有单点故障问题的。

引入了 Journal Node 集群以后,Active 状态的 NameNode 实时的往 Journal Node 集群写元数据,StandBy 状态的 NameNode 实时从 Journal Node 集群同步元数据,这样就保证了两个 NameNode 之间的元数据是一致的。

两个 NameNode 自动切换

目前虽然解决了单点故障的问题,但是目前假如 Active NameNode 出了问题,还需要我们人工的参与把 Standby NameNode 切换成为 Active NameNode,这个过程并不是自动化的,但是很明显这个过程我们需要自动化,接下来我们看 HDFS2是如何解决自动切换问题的。为了解决自动切换问题,HDFS2 引入了 ZooKeeper集群和 ZKFC 进程。

02、内存受限问题解决

前面我们虽然解决了高可用的问题,但是如果 NameNode 的元数据量很大,大到当前 NameNode 所在的服务器存不下,这个时候集群就不可用了,换句话说就是NameNode 的扩展性有问题。为了解决这个问题,HDFS2 引入了联邦的机制。

如上图所示这个是一个完整的集群,由多个 namenode 构成,namenode1 和 namenode2 构成一套 namenode,我们取名叫 nn1,这两个 namenode 之间是高可用关系,管理的元数据是一模一样的;namenode3 和 namenode4 构成一套 namenode,假设我们取名叫 nn2,这两个 namenode 之间也是高可用关系,管理的元数据也是一模一样的,但是 nn1 和 nn2 管理的元数据是不一样的,他们分别只是管理了整个集群元数据的一部分,引入了联邦机制以后,如果后面元数据又存不了,那继续扩 nn3, nn4… 就可以了。所以这个时候 NameNode 就在存储元数据方面提升了可扩展性,解决了内存受限的问题。

联邦这个名字是国外翻译过来的,英文名是 Federation,之所以叫联邦的管理方式是因为 Hadoop 的作者是 Doug cutting,在美国上学,美国是联邦制的国家,作者从国家管理的方式上联想到元数据的管理方式,其实这个跟我们国家的管理方式也有点类似,就好比我们整个国家是一个完整的集群,但是如果所有的元数据都由北京来管理的话,内存肯定不够,所以中国分了34个省级行政区域,各个区域管理自己的元数据,这行就解决了单服务器内存受限的问题。

HDFS2 引入了联邦机制以后,我们用户的使用方式不发生改变,联邦机制对于用户是透明的,因为我们会在上游做一层映射,HDFS2 的不同目录的元数据就自动映射到不同的 namenode 上。

03、HDFS2 的架构缺陷

缺陷一:高可用只能有两个 namenode

为了解决单点故障问题,HDFS2 设计了两个 namenode,一个是 active,另外一个是 standby,但是这样的话,如果刚好两个 NameNode 连续出问题了,这个时候集群照样还是不可用,所以从这这个角度讲,NameNode 的可扩展性还是有待提高的。

注意:这个时候不要跟联邦那儿混淆,联邦那儿是可以有无数个 namenode 的,咱们这儿说的只能支持两个 namenode 指的是是高可用方案。

缺陷二:副本为 3,存储浪费了 200%

其实这个问题 HDFS1 的时候就存在,而且这个问题跟 NameNode 的设计没关系,主要是 DataNode 这儿的问题,DataNode 为了保证数据安全,默认一个block 都会有 3 个副本,这样存储就会浪费了 200%。

四、HDFS3

其实到了HDFS2,HDFS就已经比较成熟稳定了,但是HDFS3还是精益求精,再从架构设计上重新设计了一下。

01、高可用之解决只能有两个namenode

当时在设计 HDFS2 的时候只是使用了两个 NameNode 去解决高可用问题,那这样的话,集群里就只有一个 NameNode 是 Standby 状态,这个时候假设同时两个NameNode 都有问题的话,集群还是存在不可用的风险,所以在设计 HDFS3 的时候,使其可支持配置多个 NameNode 用来支持高可用,这样的话就保证了集群的稳定性。

02、解决存储浪费问题

HDFS3 之前的存储文件的方案是将一个文件切分成多个Block进行存储,通常一个 Block 64MB 或者 128MB,每个 Block 有多个副本(replica),每个副本作为一个整体存储在一个 DataNode 上,这种方法在增加可用性的同时也增加了存储成本。ErasureCode 通过将 M 个数据 block 进行编码(Reed-Solomon,LRC),生成 K 个校验(parity)block,这 M+K 个 block 组成一个 block group,可以同时容忍 K 个 block 失败,任何 K 个 block 都可以由其他 M 个 block算出来。overhead 是 K/M。

以 M=6,K=3 为例,使用 EC 之前,假设 block 副本数为 3,那么 6 个 block 一共 18 个副本,overhead 是 200%,使用 EC 后,9 个 block,每个 block 只需一个副本,一共 9 个副本,其中 6 个数据副本,3 个校验副本,overhead 是 3/6 = 50%。

在存储系统中,纠删码技术主要是通过利用纠删码算法将原始的数据进行编码得到校验,并将数据和校验一并存储起来,以达到容错的目的。其基本思想是将 k 块原始的数据元素通过一定的编码计算,得到m块校验元素。对于这 k+m 块元素,当其中任意的 m 块元素出错(包括数据和校验出错),均可以通过对应的重构算法恢复出原来的 k 块数据。生成校验的过程被称为编码(encoding),恢复丢失数据块的过程被称为解码(decoding)。

Reed-Solomon(RS)码是存储系统较为常用的一种纠删码,它有两个参数 k 和m,记为 RS(k, m)。如下图所示,k 个数据块组成一个向量被乘上一个生成矩阵(Generator Matrix)GT 从而得到一个码字(codeword)向量,该向量由k个数据块和 m 个校验块构成。如果一个数据块丢失,可以用 (GT) - 1 乘以码字向量来恢复出丢失的数据块。RS(k,m) 最多可容忍 m 个块(包括数据块和校验块)丢失。

它是社区最新的 HDFS3 内部的方案,需要对整个 HDFS 内部实现进行改造,包括 DataNode,NameNode 还有 DFSClient,该方案同时支持在线和离线 EC。

03、在线 EC

当前 HDFS block 的副本作为一个整体连续(contiguous)的存储在一个DataNode 上,在 locality 上具有一定的优势,特别是对于 MapReduce 这样的应用,但是这种方法不好做在线 EC。当前社区方案不以 block 为单位进行 EC,而是以 strip 为单位进行 EC(HDFS 依旧管理 Block)设计思路参考了 QFS。对于配置了 EC 的文件,客户端写入时将文件的数据切成一个个的 64KB 的 strip,相邻的 strip 发往不同的 DataNode,比如当前使用 (6,3)-Reed-solomon 编码,当前正在写的文件有 6 个 strip:strip1, strip2, strip3, strip4, strip5, strip6,那么这 6 个 strip 和相应的编码出来的 3 个校验 strip 共 9 个 strip 会并行的发往 9 个不同的DataNode。这种方式写入性能更好,但是也会对网卡出口带来一些压力,同时牺牲了 locality。如果文件大小不是 64KB * 6 的整数倍(本文例子),那么最后一个strip group 显然不是满的,这时客户端还会将最后一个 strip group 的长度记在校验块中,后续读的时候,可以根据这个长度和数据块长度还有文件长度来校验。

对于 append 和 hflush 操作,最后一个 parity strip group 很可能还没有切换成新的 strip group,这就需要 DataNode 更新最后一个 parity strip 的数据。

读操作,丢失 block 时,只需要读 9 个 DataNode 中任意 6 个 DataNode 即可修复。修复过程需要读多个 DataNode,耗费网络带宽和磁盘 IO。

04、离线 EC

该方案也支持离线 EC,可以异步的将多副本文件转成 EC 文件,通过集成在NameNode 中的 ECManager 和 DataNode 上的 ECWorker 来支持。命令行工具提供 replication 和 ec 之间的转换,可以通过命令行配置哪些文件/目录使用 EC。在转换方程中,不支持 append。

这样的话,HDFS3 靠就删码技术解决了存储浪费的问题。

五、尾声

好了,到目前为止我们看到 HDFS,三个大的版本的演进的过程,一开始是HDFS1,HDFS1 有问题,所以就有了 HDFS2,HDFS2 就是为了解决 HDFS1 架构缺陷的,同学们,我们回过头来想想,其实 HDFS1 的那些架构设计问题,是不是我们平时的项目当中也是存在的,所以以后大家在项目中遇到类似问题的时候,不妨可以参考借鉴一下 HDFS2 的解决的思路。HDFS3 是对 HDFS2 的优化,其实 HDFS3 解决的这些问题,如果自己设计过文件系统的同学(本人自己设计过分布式图片服务器)也可用类似的思路去解决系统的高可用和副本造成存储浪费的问题。

希望能给大家带来收获,同学们加油!!!

目录
相关文章
|
7天前
|
存储 Prometheus Cloud Native
分布式系统架构6:链路追踪
本文深入探讨了分布式系统中的链路追踪理论,涵盖追踪与跨度的概念、追踪系统的模块划分及数据收集的三种方式。链路追踪旨在解决复杂分布式系统中请求流转路径不清晰的问题,帮助快速定位故障和性能瓶颈。文中介绍了基于日志、服务探针和边车代理的数据收集方法,并简述了OpenTracing、OpenCensus和OpenTelemetry等链路追踪协议的发展历程及其特点。通过理解这些概念,可以更好地掌握开源链路追踪框架的使用。
58 41
|
4月前
|
安全 应用服务中间件 API
微服务分布式系统架构之zookeeper与dubbo-2
微服务分布式系统架构之zookeeper与dubbo-2
|
4月前
|
负载均衡 Java 应用服务中间件
微服务分布式系统架构之zookeeper与dubbor-1
微服务分布式系统架构之zookeeper与dubbor-1
|
4月前
|
存储 JSON 数据库
Elasticsearch 分布式架构解析
【9月更文第2天】Elasticsearch 是一个分布式的搜索和分析引擎,以其高可扩展性和实时性著称。它基于 Lucene 开发,但提供了更高级别的抽象,使得开发者能够轻松地构建复杂的搜索应用。本文将深入探讨 Elasticsearch 的分布式存储和检索机制,解释其背后的原理及其优势。
312 5
|
17天前
|
设计模式 存储 算法
分布式系统架构5:限流设计模式
本文是小卷关于分布式系统架构学习的第5篇,重点介绍限流器及4种常见的限流设计模式:流量计数器、滑动窗口、漏桶和令牌桶。限流旨在保护系统免受超额流量冲击,确保资源合理分配。流量计数器简单但存在边界问题;滑动窗口更精细地控制流量;漏桶平滑流量但配置复杂;令牌桶允许突发流量。此外,还简要介绍了分布式限流的概念及实现方式,强调了限流的代价与收益权衡。
60 11
|
19天前
|
设计模式 监控 Java
分布式系统架构4:容错设计模式
这是小卷对分布式系统架构学习的第4篇文章,重点介绍了三种常见的容错设计模式:断路器模式、舱壁隔离模式和重试模式。断路器模式防止服务故障蔓延,舱壁隔离模式通过资源隔离避免全局影响,重试模式提升短期故障下的调用成功率。文章还对比了这些模式的优缺点及适用场景,并解释了服务熔断与服务降级的区别。尽管技术文章阅读量不高,但小卷坚持每日更新以促进个人成长。
45 11
|
21天前
|
消息中间件 存储 安全
分布式系统架构3:服务容错
分布式系统因其复杂性,故障几乎是必然的。那么如何让系统在不可避免的故障中依然保持稳定?本文详细介绍了分布式架构中7种核心的服务容错策略,包括故障转移、快速失败、安全失败等,以及它们在实际业务场景中的应用。无论是支付场景的快速失败,还是日志采集的安全失败,每种策略都有自己的适用领域和优缺点。此外,文章还为技术面试提供了解题思路,助你在关键时刻脱颖而出。掌握这些策略,不仅能提升系统健壮性,还能让你的技术栈更上一层楼!快来深入学习,走向架构师之路吧!
55 11
|
23天前
|
自然语言处理 负载均衡 Kubernetes
分布式系统架构2:服务发现
服务发现是分布式系统中服务实例动态注册和发现机制,确保服务间通信。主要由注册中心和服务消费者组成,支持客户端和服务端两种发现模式。注册中心需具备高可用性,常用框架有Eureka、Zookeeper、Consul等。服务注册方式包括主动注册和被动注册,核心流程涵盖服务注册、心跳检测、服务发现、服务调用和注销。
62 12
|
1月前
|
消息中间件 架构师 数据库
本地消息表事务:10Wqps 高并发分布式事务的 终极方案,大厂架构师的 必备方案
45岁资深架构师尼恩分享了一篇关于分布式事务的文章,详细解析了如何在10Wqps高并发场景下实现分布式事务。文章从传统单体架构到微服务架构下分布式事务的需求背景出发,介绍了Seata这一开源分布式事务解决方案及其AT和TCC两种模式。随后,文章深入探讨了经典ebay本地消息表方案,以及如何使用RocketMQ消息队列替代数据库表来提高性能和可靠性。尼恩还分享了如何结合延迟消息进行事务数据的定时对账,确保最终一致性。最后,尼恩强调了高端面试中需要准备“高大上”的答案,并提供了多个技术领域的深度学习资料,帮助读者提升技术水平,顺利通过面试。
本地消息表事务:10Wqps 高并发分布式事务的 终极方案,大厂架构师的 必备方案
|
1月前
|
存储 算法 安全
分布式系统架构1:共识算法Paxos
本文介绍了分布式系统中实现数据一致性的重要算法——Paxos及其改进版Multi Paxos。Paxos算法由Leslie Lamport提出,旨在解决分布式环境下的共识问题,通过提案节点、决策节点和记录节点的协作,确保数据在多台机器间的一致性和可用性。Multi Paxos通过引入主节点选举机制,优化了基本Paxos的效率,减少了网络通信次数,提高了系统的性能和可靠性。文中还简要讨论了数据复制的安全性和一致性保障措施。
43 1

热门文章

最新文章

下一篇
开通oss服务