vlambda博客
学习文章列表

学习笔记 | Apache Hadoop Ozone 浅析

Apache Hadoop Ozone是当前Apache Hadoop生态圈的一款新的对象存储系统,可用于小文件和大文件存储,它特别适合来作为新一代的统一数据湖对象存储系统,数据湖是一种在系统或存储库中以自然格式存储数据的方案,它有助于以各种模式和结构形式配置数据,通常是对象块或文件。OZone与HDFS有着很深的关系,在设计上也对HDFS存在的不足做了很多改进,使用HDFS的生态系统可以无缝切换到OZone。

HDFS有哪些不足

HDFS在可扩展性上的缺陷,以及对小文件的不友好,限制了HDFS在许多场景下的应用。Apache Hadoop HDFS从出现到现在经过10多年的发展,已经到了非常成熟的状态,广泛应用于业界,解决海量文件的存储需求。但随着数据量的增长,以及对于数据使用方式的多样化,HDFS的架构局限性就逐渐被放大,NameNode在大规模场景很容易成为瓶颈:

元数据的扩展性:NameNode是一个中央元数据服务节点,也是集群管理节点,文件系统的元数据以及块位置关系全部在内存中。NameNode对内存的要求非常高,需要定制大内存的机器,内存大小也限制了集群扩展性。京东的NameNode采用内存512GB的机器,字节跳动的NameNode采用内存1TB的机器。此外,NameNode的堆分配巨大,京东的NameNode需要360GB的堆大小,对GC的要求比较高,京东定制化的JDK11+G1GC在GC时性能良好,但是一般规模的公司不具备维护JDK能力,该方案不具备普遍性。字节跳动把NameNode修改成C++版本,这样分配、释放内存都由程序控制,也达到了不错的性能,该方案仍然不具普遍性,因为开发和维护C++版本的NameNode也需要不小规模的团队。

GC是垃圾收集的意思(Gabage Collection), 内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃

块汇报风暴:HDFS块大小默认128M,启动几百PB数据量的集群时,NameNode需要接受所有块汇报才可以退出安全模式,因此启动时间会达数小时。当集群全量块汇报、下线节点、balance集群存储,也会对集群元数据服务的性能造成影响,这些根本原因都是DataNode需要把所有块汇报给NameNode。

全局锁:NameNode有一把FSNamesystem全局锁,每个元数据请求时都会加这把锁。虽然是读写分开的,且有部分流程对该锁的持有范围进行了优化,但依然大问题。同时FSNamesystem内部的FSDirectory(Inode树)还存在一把单独的锁,用来保护整棵树以及BlockMap的访问和修改。

Apache Hadoop Ozone的针对性优化

为了解决HDFS的上述问题,Hadoop社区推出分布式key-value对象存储系统Ozone,兼容文件访问接口。利用Hadoop Compatible FileSystem接口, Ozone可以用于大数据生态;利用CSI,S3协议, Ozone可以作为云存储服务云上用户。 


Ozone架构分为三个部分,OzoneManager、StorageContainerManager、Datanode。OzoneManager相当于HDFS的Namespace元数据;StorageContainerManager相当于HDFS的Block Manager,但管理的是Container而不是HDFS的Block。而Datanode使用Raft实现的Ratis保证写一致性。

学习笔记 | Apache Hadoop Ozone 浅析


HDFS的三个局限,Ozone采用如下方式解决:

Ozone把Namespace元数据服务和Block Manager拆分为两个服务。OzoneManager负责元数据服务;StorageContainerManager负责数据块管理、节点管理、副本冗余管理。两个服务可以部署在两台机器,各自利用机器资源。Ozone的元数据不像NameNode存储在内存中,不管是OzoneManager的元数据,还是StorageContainerManager中的Container信息都维护在RocksDB中,极大降低对内存的依赖,理论上元数据可以无限扩展。

StorageContainerManager无须管理默认128MB的Block,只需管理默认5GB的Container。极大地减少了StorageContainerManager管理的数据量,从而提升StorageContainerManager的服务性能。因为StorageContainerManager是以Container作为汇报单位,汇报数量比HDFS大大减少。无论是全量块汇报,增删副本,balancer集群存储,都不会给StorageContainerManager性能造成很大影响。

OzoneManager内部的锁是Bucket级别,可以达到Bucket级的写并发。Ozone是对象存储,对象语义的操作,不存在目录和树的关系,因此不需要维护文件系统树,可以达到高吞吐量。

Ozone的结构中保留了原先HDFS中的 DataNode数据节点,不过将管理元数据的NameNode分拆成了Ozone Manager(处理用户请求和响应)和Storage Container Manager(管理数据pipeline,container等资源)。数据节点上从原先的Block管理数据转变成了Container管理,同时也采用了更为轻量的Raft协议管理元数据和数据的一致性。Ozone Manager和Storage Container Manager放在了性能更好的RocksDB内管理,大大增加了集群Scale Out的能力,在架构上突破了原先HDFS元数据瓶颈的限制,同时也通过Raft增加了元数据管理节点standBy的个数,增强了集群可用性。

Ozone利用了Raft协议作为集群一致性协议,写数据时通过DataNode Raft Leader同步到Follower的方式确保多副本写入,读数据时只需要读到任意副本都可以返回结果,从而达到强一致的读写语义。

Raft选举机制

分布式系统的一致性问题是大家津津乐道的话题,分布式系统由于本身分布式处理和计算的特点,需要协调各个服务器节点的服务状态保持一致来保证系统的容错能力,当某些节点出现故障的时候,不至于拖累整个集群。尤其对于Ozone这样的强一致分布式存储系统,需要在节点间有广泛承认的协议来保证状态一致,Ozone采用了Raft协议来维护集群状态和共享数据。

Raft协议中会有3个角色身份:Leader,Follower和Candidate。Split Vote投票过程会在Candidate中选出Leader和Follower的身份,Follower可以变成Candidate竞选Leader。


Raft协议本质上是通过本地的RaftLog和在Leader与Follower之间同步状态来保证数据的一致性,同时StateMachine会记录集群的状态。RaftLog使用了write ahead log (WAL) 的理念,Leader将过程记录在Log里面,同时日志的更新内容会同步到Follower上,然后日志会apply log到StateMachine中记录状态,当有足够的Quorum宣布成功,整体操作就成功了。这样能保证集群所有节点的状态机变化是相对同步的,同时RaftLog会在节点重启时做replay回放操作,重新建立起重启前的StateMachine状态,让节点恢复到与重启前相对同步的状态。

从Ozone写入过程的container流程中,为了保证当前三副本的冗余机制,container需要在3个数据节点DataNode上分配空间并保证多数节点写成功。Raft协议中的日志机制可以保证在Leader写完成后,Replicate数量到follower上去,三副本中有一个follower写完成后,数据就持久化成功了。这个大多数数据写成功的操作可以直接由Raft协议帮助完成,同时可以保证读写强一致。

Ozone的数据写入模式

Ozone对于数据的管理主要由Pipeline和Container完成。Ozone的Storage Container Manager (SCM)负责创建数据Pipeline,并且分配Container到不同的Pipeline中,而每个Container负责在不同的数据节点DataNode上分配Block用来存储数据。用户通过客户端写入Ozone,会通过Ozone Manager创建Key,并从SCM拿到数据可以写入的空间,这个空间会由Pipeline和Container分配得来。

Pipeline和Container分配写入数据跟数据的副本数有关,Ozone现在主要支持三副本的方式,数据Pipeline创建时会关联三个数据节点,然后相关的Container会在这三个数据节点上分配Block来完成写入空间分配,三个数据节点会分别记住Pipeline和Container信息,异步发送Report到SCM上报Pipeline和Container的状态。三副本的数据Pipeline是通过Raft协议保证多副本一致性,在Ozone中也叫Ratis Pipeline,相关的三个数据节点会根据Raft协议组成一个Leader和2个Follower的组合,数据写入时会利用RaftLog把数据从leader发到Followers。所以Ozone的数据写入的性能依赖RaftLog的写入吞吐量和传输速度。

Ozone的数据节点写入磁盘的部分,一定程度上延续了HDFS单节点写入的方式,同时也保留了一些可待优化的部分。例如比起单纯在数据节点上做IO栈层面的优化,可以利用数据Pipeline的节点复用和RaftLog的特点,加大了数据节点对于并发写入数据的参与度,这样通过元数据和管理成本的修改增大写入带宽的方式。


目前Apache Hadoop Ozone在企业服务中的商用案例并不多,随着社区的热度兴趣和各大厂牌对其进行优化探索和内部验证,在今后的道路上或许值得我们期待。