HDFS是业界默认的大数据存储系统,在业界的大数据集群中有非常广泛的使用。HDFS集群有着很高的稳定性且易扩展得益于它较简单的构架,但包含几千个节点,保存上百拍比特(PB)数据的集群也不鲜见。我们简单来回顾一下HDFS的构架,如图1所示。
▲图1 HDFS构架
HDFS通过把文件系统元数据全部加载到数据节点Namenode内存中,给客户端提供了低延迟的元数据访问。由于元数据需要全部加载到内存,所以一个HDFS集群能支持的最大文件数,受Java堆内存的限制,上限大概是4亿~5亿个文件。所以HDFS适合大量大文件[几百兆字节(MB)以上]的集群,如果集群中有非常多的小文件,HDFS的元数据访问性能会受到影响。虽然可以通过各种Federation技术来扩展集群的节点规模,但单个HDFS集群仍然没法很好地解决小文件的限制。
基于这些背景,Hadoop社区推出了新的分布式存储系统Ozone。Ozone能够轻松管理小文件和大文件,是一个分布式Key-Value对象存储系统。
01基本概念
对象存储是一种数据存储,每个数据单元存储为离散单元(称为对象)。对象可以是任何类型、任何大小的数据。语义上,对象存储中的所有对象都存储在单个平面地址空间中,没有文件系统的层次结构。实现中,为了支持多用户及用户隔离,更好地管理和使用对象,通常对象存储也会在平面的地址空间中划分出几个层次。这些层次是由对象存储的实现确定的,每个层次都有特定的语义,用户不能更改。
Ozone的对象层次分三个层次,从上到下依次是Volume(卷),Bucket(存储桶)和Object(对象),如图2所示。
▲图2 Ozone的对象层次
1、Volume(卷)
Volume类似Amazon S3中用户账户的概念,是用户的Home目录。Volume只有系统管理员才可以创建,是存储管理的单位,比如配额管理。Ozone建议系统管理员为每个用户都单独创建独立的Volume。Volume用来存储Bucket,目前一个Volume下面可以包含任意多个Bucket。
2、Bucket(存储桶)
存储桶是对象的容器,概念类似于S3的Bucket,或者Azure中的Container。存储桶创建于Volume下,只能属于一个Volume,创建后归属关系不可更改,也不支持更改存储桶的名字。Amazon S3的存储桶名称是全局唯一的,并且命名空间由所有AWS账户共享。这意味着,在创建存储桶之后,任何AWS区域中的其他AWS账户均不能使用该存储桶的名称,直至删除该存储桶。在Ozone中,存储桶名称只需要确保在本Volume内部是唯一的。不同的Volume可以创建名称相同的存储桶。
3、Object(对象)
对象存储在存储桶中,是键+值的存储。键是对象的名称,值是对象的内容。对象的名称在所属存储桶中必须是唯一的。对象有自己的元数据,包括值的大小、创建时间、最后一次修改时间、备份数、访问控制列表ACL等。对象的大小没有限制。
Ozone支持URL以虚拟主机方式的访问Ozone的对象。它采用如下格式:
[scheme][bucket.volume.server:port]/key
其中,scheme可以选:1)o3fs,通过RPC协议访问Ozone。2)HTTP/HTTPS,通过HTTP协议访问Ozone REST API。当scheme省略时,默认使用RPC协议。server:port是Ozone Manager的地址。如果没有指定,则使用集群的配置文件ozone-site.xml中“ozone.om.address”值。如果配置文件中也没有定义,则默认使用“localhost:9862”。
02技术架构
Ozone技术构架分为三个部分:Ozone Manager,统一的元数据管理;Storage Container Manager,数据块分配和数据节点管理;Datanode,数据节点,数据的最终存放处,如图3所示。类比HDFS的构架,可以看到原来的Namenode的功能,现在由Ozone Manager和Storage Container Manage分别进行管理。对象元数据空间和数据分布分开管理,有利于两者的独立按需扩展,避免之前Namenode单节点的压力。
▲图3 Ozone技术构架
Ozone主要模块和功能如下。
1、Ozone Manager(OM)
Ozone Manager是管理Ozone的命名空间,提供所有的Volume(卷)、Bucket(存储桶)和Key(键)的新建、更新和删除操作。它存储了Ozone的元数据信息,这些元数据信息包括Volumes、Buckets和Keys,底层通过RATIS(实现了RAFT协议)扩展元数据的副本数来实现元数据的HA。Ozone Manager只和Ozone Client和Storage Container Manager通信,并不直接和Datanode通信。Ozone Manager将命名空间的元数据存储在RocksDB中,避免了HDFS中需要将所有元数据都保留在内存,从而经常会受到小文件问题的困扰。RocksDB是Facebook基于LevelDB开发的一个本地Key-Value存储引擎,尤其对于SSD有很多的优化和改进,提供高吞吐量的读写操作。
2、Storage Container Manager(SCM)
SCM类似HDFS中的Block Manager,管理Container,写Pipelines和Datanode,为Ozone Manager提供Block和Container的操作和信息。SCM也监听Datanode发来的心跳信息,作为Datanode Manager的角色,保证和维护集群所需的数据冗余级别。SCM和Ozone Client之间没有通信。
3、Block、Container和Pipeline
Block是数据块对象,真实存储用户的数据。Container中的一条记录是一个Block的信息,每个Block在Container里面有且仅有一条记录,如图4所示,在Ozone中,数据是以Container为粒度进行副本复制的。SCM中目前支持2种Pipeline方式,由单Datanode节点组成的Standalone读Pipeline,和由三个Datanode节点组成的Apache RATIS写Pipeline。Container有2种状态,OPEN和CLOSED。当一个Container是OPEN状态时,可以往里面写入新的Block。当一个Container达到它预定的大小时(默认5GB),它从OPEN状态转换成CLOSED状态。一个Closed Container是不可修改的。
▲图4 Datanode Container内部结构
由三个Datanode节点组成的Apache RATIS写Pipeline,保证数据一旦落盘,后续总能读到最新的数据,数据是强一致的,并且每份数据有3个备份,不用担心由于单个磁盘故障导致的数据丢失,如图5所示。
▲图5 RATIS写Pipeline
4、Datanode
Datanode是Ozone的数据节点,以Container为基本存储单元维护每个Container内部的数据映射关系,并定时向SCM发送心跳节点、汇报节点的信息、管理Container的信息和Pipeline的信息。当一个Container大小超过预定大小的90%时或者写操作失败时,Datanode会发送Container Close命令给SCM,把Container的状态从OPEN转变成CLOSED。或者当Pipeline出错时,发送Pipeline Close命令给SCM,把Pipeline从OPEN状态转为CLOSED状态。
5、分层管理
Ozone分层结构使得Ozone Manager、Storage Container Manager和Datanode可按需独立扩展。对于Ozone提供的语义,也是分层管理的,如图6所示。
▲图6 Ozone语义与对应的管理模块
6、对象创建
当Ozone Client(客户端)需要创建并且写入一个新对象时,客户端需要和Ozone Manager和Datanode直接打交道,具体过程如图7所示。
▲图7 创建Ozone新对象
1)Ozone客户端链接Ozone Manager,提供需要创建的对象信息,包括对象的名称、数据的大小、备份数和其他用户自定义的对象属性。
2)Ozone Manager收到Ozone客户端的请求后,和SCM通信,请求SCM寻找能够容纳数据的处于OPEN状态的Container,然后在找到的Container中分配足够数量的Block。
3)SCM将新对象数据将要写入的Container、Block和Container所在的Pipeline的三个Datanode的信息列表返回给Ozone Manager。
4)Ozone Manager将收到SCM返回的信息,返回给客户端。
5)客户端得到Datanode列表信息之后,和第一个Datanode(Raft Pipeline Leader)建立通信,将数据写入Datanode的Container。
6)客户端完成数据写入后,连接Ozone Manager,确认数据已经更新完成,Ozone Manager更新对象的元数据,记录对象数据所在的Container和Block的信息。至此,新的对象创建完成。之后,其他的客户端就可以访问这个对象了。
7、对象读取对象读取的过程相对简单,类似于HDFS的文件读,如图8所示。
▲图8 读取Ozone对象
1)Ozone Client(客户端)和Ozone Manager通信,制定要读取的对象Key (/volume/bucket/key)。
2)Ozone Manager在元数据库中查找对应的对象,返回对象数据所在的Container和Block信息,包括Container所在的Datanode列表信息给Ozone Client(客户端)。
3)Ozone支持Data locality。如果Ozone Client(客户端)运行在集群中的某个节点上,Ozone Manager会返回按照网络拓扑距离排序的Datanode列表。Ozone Client(客户端)可以选择第一个Datanode节点(本地节点),也是离Client(客户端)最近的节点来读取数据,节省数据读取的网络传输时间。