背景
互联网的发展日新月异,每天产生的各种数据爆炸式增长,下面是来自一些重要领域的统计数据。
1、到2025年,全球数据领域将有 175 ZB 的数据(来自 Seagate UK)。
1字节(Byte) = 8位(bit)
1KB( KB,千字节) = 1024B
1MB( MB,兆字节) = 1024K
1GB( GB,吉字节,千兆) = 1024MB
1TB( TB,万亿字节,太字节) = 1024GB
1PB( PB,千万亿字节,拍字节) = 1024TB
1EB( EB,百亿亿字节,艾字节) = 1024PB
1ZB(ZB,十万亿亿字节,泽字节) = 1024EB
2、Google、Facebook、Microsoft 和Amazon 至少存储了1200PB 的信息(来自 Science Focus)。
3、截至2020年7月,全球五联网用户超过48亿(来自Internet World Stats)。
4、截至2020年3月,字节跳动拥有近10亿固定用户(来自维基百科)。
不仅数据量庞大,而且数据的形式多种多样,有音视频、图片、文字,甚至还有最基础的二进内容,因此如何安全、高效地存储及访问这些数据显得尤为重要。同时还应该考虑存储的兼容性及前瞻性,因为数据还在持续增长。
当前存储数据的介质产品非常丰富。例如,单台机器就能轻松存储数十TB 数据,不过使用单机存储数据存在以下不足:
1、容量大小受限,存在存储上限
2、访问受限,通常只能允许数十个用户同时访问
3、故障保障低,一旦机器出现问题,有可能造成所有用户都不能正常访问
针对以上不足,很多企业通常会选择分布式存储系统来存储量级较大的数据。什么是分布式存储?通俗地讲,**分布式存储是指采用便捷的分布式网络,将数据分散地存储在多台独立的机器设备上,同时利用多台存储服务器分担存储负荷,**利用数据管理服务器定位存储信息,从而提高系统的可靠性、可用性和存取效率,易于拓展。
一、分布式文件系统部署架构
基于中心化的系统具有良好的稳定性,且实施复杂度低。这种分布式系统集群存在部分管理节点(Master)和数据节点(Slave)。
基本架构分为3部分,各部分主要作用如下:
Maste r:负责文件定位、维护文件元 (meta) 信息、集群故障检测、管理数据迁移、分发数据备份、提供有关数据的操作命令或对外调用接口。
**Slave:**负责提供数据的存储介质,定期和 Master交互汇报自身的数据信息,或执行 Master 分发的命令,同时也会对外提供一些可访问的接口方式。
**Client:**通常是一组需要计算的任务,或者仅执行数据的获取任务。在有中心节点的架构下,通常会先和Master交互,然后根据位置信息再和Slave通信。在有中心节点的部署方案里,一般中心节点并不参与真正的数据读写,而是将文件 meta 信息保存并管理起来,Client从Master获取meta信息之后即可与slave通信。
二、HDFS的服务视图
核心服务
**Namenode:**HDFS 系统采用中心化设计,即 Master/Slave 架构。这里的Namenode即是 Master,作用是管理整个文件系统的meta信息并管理Client对文件的访问。一个HDFS集群可以由多个namenode组成。
**DataNode:**DataNode 是 HDFS中的Slave 角色,主要作用是存储从Client 写入的数据,并负责处理来自Client的直接读写请求。DataNode还会处理来自Namenode 的指令。一个HDFS集群可以音龙百上千个 DataNode 节点。
**HA (High Availability,高可用):**HDFS 提供了高可用机制。在实际使用中,一个集群会部署两个Namenode节点,一个处于Active 状态,另一个处于 Standby 状态。Active Namenode 负责集群户端操作。当集群发生故障,Active 节点不可用时,HDFS 会快速完成状态转移,原先 Standby变成Active状态,原先Active 节点会变成Standby 状态,从而保障集群正常工作。
**Namespace:**随着业务访问量的增大,一个Active Namenode 在处理所有 Client 请求时会存这时需要对该Namenode 减压。一种有效的方法是将原先一个Namenode处理的业务分离出去一部分。因此,HDFS提供了Namespace 的概念,支持部署多个 Namespace,由每个 Namespace处理一部分client的请求。
**Snapshot (快照):**快照是数据在某个只读时间上的副本,通常是用来作为数据备份,防止用户误操作,实现数据的容灾恢复。
**FsImage:**Client 访问过的数据对应的 meta 会在Namenode 中记录,并分别在两处保存。一处是在Namenode内存中,另一处是在硬盘。Namenode会定期将内存中的结构数据持久化,持久化的这部分数据成为FsImage,主要作用是防止数据丢失。
**Edits:**Client 访问HDFS 时,如果是更新操作,会生成一条 Transaction 记录,记录本次操作的具体内容。这个记录会被保存到 Edits 文件中,之后会定期被Standby Namenode处理。
**Cache Management:**在 HDFS 中,Cache 采用集中式管理。Cache 的使用能有效提升 Client读写数据的效率。
**Native Libraries (本地):**本地的作用是可以提高压缩和解压的效率,同时提供本地方法调用接口,比如和C、C++交互。
**Quotas(限流):**当访问HDFS 的Client不断增加、集群存在压力时,需要适当控制流入HDFS 的请求。HDFS 提供了Ouotas 限流功能,可以对文件数量和流量限流。
**Interface:**HDFS 提供了对外接人的统一访问接口,可以支持 RPC、REST或C API
**Slorage Policies:**HDFS支持的存储非常丰富,有 DISK、SSD、内存存储、Archive和第三方存储介质。存储策略上支持热存储、温存储、冷存储等。
**Thanspruret Bneypton:**HDFS中的加密是透明的端到端的。对数据加密后,无须Client修改程序。
**Thind Party Support:**HDFS 提供了对第三方的拓展机制,支持对 Amazon S3、OpenStack等的拓展,也支持自定义一些特性。
**Upgrade/Dowmgrade:**当有新版本需要替换时,HDFS提供滚动升级和滚动降级版等功能。
**Rack (机架):**Hadoop 组件都能识别机架感知,HDFS 也不例外。数据块 ( Block) 副本放置在不同机架上可以实现容错,这是使用机架感知来实现的。通过网络交换机和机器位置可以在机器故障的情况下区分数据的可用性。
公共服务(处理统一流程)
**Secure Mode:**HDFS的安全功能包括身份认证、服务级别授权、Web 控制合身份验证和数据机密性验证等。
**Authentication:**HDFS 的权限和认证支持很强大。可以通过 Kerberos、SSL认证、Posix样式权限和Ranger授权。
**Service Level:**服务层级花费是 HDFS 的一大亮点,可以支持让某些用户只访问其中一部分服务来控制集群风险,如只运行 User A访问 DataNode服务
**Proxy User:**HDFS 的用户系统支持超级用户、普通用户和代理用户。其中,代表另一个用户问HDFS集群的用户被称为代理用户。
拓展服务
通常用来辅助管理集群,比如额外使用的工具、提供测试功能等。
三、HDFS的架构(Master/Slave)
Namenode管理文件系统的 Metadata,并处理 Client 请求。
发生故障时,Active Namenode和Standby Namenode 快速实现高可用(HA)。
Client访问时,先通过 Namenode定位文件所在位置,然后直接和 Datanode 交互。
Client 写人的数据会以数据块 (Block) 的形式存储在个 Datanode,每个 Block 通常会有多个副本(Replication)。
HDFS通常会部署多个 Datanode 节点,这些节点在机架 (Rack) 上有各自的位置。
四、元数据架构
背景:
和很多分布式存储系统一样,HDFS 有自己独特的元数据架构。元数据在HDFS中以两种形式被维护:一个是内存,时刻维护集群最新的数据信息;另一个是磁盘,对内存中的信息进行维护存人内存是为了快速处理 Client 的请求,存储磁盘是为了将数据持久化,以便于在故障发生时能够及时恢复。
介绍namenode的启动(包含加载元数据)
加载预先生成的持久化文件FsImage
**注:**FsImage 是一种持久化到磁盘上的文件,里面包含了集群大部分的 meta数据,持久化的目的是为了防止 meta数据丢失,也就是在 HDFS 不可用的情况下还能够保证绝大多数的数据是正常的。
加载没有完成处理的Edit Log
**注:**FsImage保存了集群大部分的 meta而且Fsmage 定期被持久化,对于一个处理在线业务的分布式系统,这样是为了保证存储数据不丢失。还有另外一部分 meta 被单独持久化,这就是 Edit Log,Edit Log和事务相关。系统宕机,记录会消失。
等待Slave节点注册和汇报其所包含的Block数据
Edit Log加载顺序:
meta视图:
meta数据(由namenode管理)-- 关于文件或目录的描述信息,如文件路径、名称、文件类型等,这些信息被称为元(meta)数据。
对文件来说,包括文件的 Block、各 Block 所在 DataNode,以及它们的修改时间、访时间等;
对目录来说,包括修改时间和访问权限控制信息,如权限、所属组等。
meta数据采用内存和持久化的方式维护。
Namenode以树形结构维护在内存中的meta,被称为内存 Tree。每次有新的请求时,都会实时同步内存tree,同时在Edit Log中产生一条Transaction,内存tree会定期被持久化。
五、NameNode管理、DataNode注册
Namenode作为Master 节点,除了负责管理数据外,还负责管理资源。这里所说的资源其实就是指对DataNode的管理。
DataNode启动后会定期向Namenode发送心跳,以此向Namenode证明自己还处存活状态。
此时 Namenode 会处理心跳信息,如发现此前没有保存 DataNode 的信息,这时会通知DataNode做一次注册。注册的目的是为了检测该DataNode是否是"意外节点"。
Datanode定时通过RPC一次性将所有Block数据发给namenode,超出阈值会分批report。
六、active node和standby namenode
active namenode
● 处理客户端的读写请求
● 维护Namespace的文件和目录
● 维护整个Namespace下的 meta
● 管理 DataNode
● 维护Block副本(不同namespace)
standby namenode
● 维护 Namespace 下的 meta
● HA备份(自动感知namenode状态并自动切换)
● 通知Edit Log 文件刷新
● 触发 Checkpoint(持久化)
七、通信(HDFS RPC)
RPC(Remote Procedure Call)在HDFS中应用广泛,无论是来自 Client 的请求,或是集群间资源调度。它以Protocol Buffers 为基础,可以实现轻量化的高效数据访问,以及持久化等功能。
Protocol Buffers是Google 开源的用于序列化结构性数据的语言无关平台无关、具有可拓展机制的数据存储格式。很适合做数据存储或 RPC 数据交换格式。目前提供了 Java C++、C#、Dart、Go、Kotlin和Python等语言支持,这也是HDFS 支持多语言的基础。
gRPC(google):
gRPC是Google开源的一个高性能、通用RPC框架,以Protocol Buffers为其IDL(接口定义语言)和底层数据交换格式。可以在过程中实现服务负载均衡、跟踪、健康检查和身份认证检查,并且提供了数据中心内和跨数据中心连接请求,非常适用于分布式系统中。同其他 RPC 实现一样,只要在Client和Server端实现相同接口的不同外理逻辑即可像在本地访问一样。
Client在正式向 Server 发送请求前,会对数据进行持久化处理,在数据经过网络的过程中,访问也会被编码,保证数据安全且尽量减少对网络资源的占用,访问到达Server 前会被解码,待用到数据时,也会被反向序列化。之后 Server 端会对做具体的处理逻辑,返回过程中会做相同的编解码机制。
Socket技术通常用于创建客户端-服务器模型。在这种模型中,服务器程序在特定的IP地址和端口上等待客户端连接,客户端则通过Socket连接到服务器程序并进行通信。通过Socket技术,可以实现不同操作系统和编程语言之间的通信,使得网络应用程序的开发更加灵活和方便。
八、位置策略
Block 是相对于 Namenode 来说的,以元数据和视图的形式呈现。
副本是实际存在于 DataNode 节点上的物理空间。副本位置策略决定了副本在集群内的存储位置,由位置选择策略和存储策略共同决定。副本存储位置选择是否合适会对读写性能及数据高可用性造成影响。
这里机架级别的位置策略(BlockPlacementPolicyRackFaultTolerant):这种策略可以实现机架级的容灾。
如果副本数小于集群中的机架数量,则随机选择机架中的节点。
如果副本数大于集群中的机架数量,准确填充每个机架副本。如果还有剩余副本数没有被安置,则为每个机架多放置1个副本,直到达到副本数量。
九、ZKFC解
HA (High Availability)是 HDFS 支持的一个重要特性,可以有效解决Active Namenode遇到故障时,将可用的 Standby 节点变成新的 Ative 状态的问题,使集群能够正常工作。目前支持两种方式:冷切换通过手动触发,缺点是不能够及时恢复集群。
实际生产中以应用热切换为主,通过自主检查 Namenode健康状态、Zookeeper 维护 Active信息、多种 namenode隔离方案,可以动态感应故障发生并实现自主切换。伴随有 ZKFC 运行进程的 Namenode都会参与选举。
ZKFC的默认实现者是DFSZKFailoverController,运行的时候需要独立开启一个JVM进程,并且和NameNode位于同一个节点--这样可以近距离的观察Namenode的状态。
ZKFC主要由以下几个部分组成:
HealthMonitor:负责及时获取本地Namenode的监控状态,辅助ActiveStandbyElector做参考。
ActiveStandbyEletor:控制和监控ZK上的节点的状态。
DFSZKFailoverController:协调HealMonitor和ActiveStandbyElector对象,处理它们发来的event变化事件,完成自动切换的过程。
ZK的状态变化及策略处理:
ZKFC除了及时知道本地Namenode状态外,还需要了解其余 Namenode 节点是否存活,这样做目的是在任何满足选举的情况下进行更新,实现的方式--Zookeeper 的分布式锁。
当某个namenode被选举成为active时,会创建两个znode:
ActiveStandbyElectorLock: 临时 node。表示创建本节点成功,意味着谁属于 Active。znode会存Active 节点信息。
ActiveBreadCrumb:永久znode。防止active的namenode非正常状态退出后恢复导致异常。
十、缓存
分布式缓存和本地缓存的比较:
● 支持大数据量缓存
● 支持高可用、高吞吐的性能
● 访问性能低于本地
**memory-locality:**cache是由NameNode统一管理的,那么HDFS client(例如MapReduce、Impala)就可以根据block被cache的分布情况去调度任务。
例如:hdfs cacheadmin -addDirective -path /user/hive/warehouse/fact.db/city -pool financial -replication 1
DFSClient读取文件时向NameNode发送getBlockLocations RPC请求。NameNode会返回一个LocatedBlock列表给DFSClient,这个LocatedBlock对象里有这个block的replica所在的DataNode和cache了这个block的DataNode。可以理解为把被cache到内存中的replica当做三副本外的一个高速的replica。