Hadoop小文件利器Ozone调研

之前一篇文章介绍了在小文件合并方面的一些心得,本篇介绍下Hadoop解决小文件的最新利器Ozone(本篇基于0.3.0-alpha版本)

Ozone诞生的背景

众所周知,HDFS是大数据存储系统,并在业界得到了广泛的使用。但是无论大集群还是小集群其扩展性都受NN的限制,虽然HDFS可以通过Federation进行扩展,但是依然深受小文件和4亿个文件的困扰

于是分布式key-value存储系统Ozone诞生了,Ozone能够轻松管理小文件和大文件。(HDFS提供了类似POSIX的语义,Ozone的外观和行为更像一个Object存储系统。)

Ozone

Ozone是专门为Hadoop设计的可扩展的分布式对象存储系统。Hadoop生态中的其它组件如Spark、Hive和Yarn不需要任何修改就可以直接运行在Ozone之上。Ozone的使用方式也较为丰富,可以通过命令行直接使用也有java客户端接口,而且接口支持RPC和REST。

Ozone由volumes、buckets和Keys组成,其中
Volumes只有管理员能够创建和删除,类似账号的概念,管理员一般都是给某个团队或者组织创建一个Volume。
Buckets有点像目录,不过这个只能有一层,因为Buckets中不能包含其它Buckets。Buckets是在Volume下,一个Volume可以包含n个Buckets,但是Buckets下面只能是Keys
Keys就是具体的对象,在Buckets中是唯一的,其名字可以是任意字符串,其值就是需要存储的数据,也就是具体的文件。目前ozone对key的大小没有限制,bucket可以包含n个keys。

有个小疑问–key就是对象,没有目录的概念,那么原hdfs某个目录下的n个小文件对应n个key?如何一次读取所有相关的key呢?比如hive加载某个分区呢?

设计原则

Ozone是由一群对大规模Hadoop集群有着丰富运维和管理经验的工程师设计开发的,因此HDFS在实践中的优缺点深刻的影响着Ozone的设计和优化。

  1. Strongly Consistent
  2. Architectural Simplicity
    当系统出现问题时,一个简单的架构更容易定位,也容易调试。Ozone尽可能的将架构进行简单化,即使牺牲掉一些可扩展性,但是在扩展性上Ozone并不逊色。Ozone目前在单个集群上可以存储10亿个对象。
  3. Layered Architecture
    为了提高Ozone的扩展性,Ozone采用分层的文件系统。Ozone将namespace management与块和节点管理层分开,允许用户分别对其进行扩展。
  4. Painless Recovery
  5. Open Source in Apache
  6. Interoperability with Hadoop Ecosystem
    Ozone可以被现存的Hadoop生态和相关的应用(如 apache hive、apache spark 和传统的 mapreduce)使用,因此Ozone支持:

Hadoop Compatible FileSystem API(也叫OzoneFS) – hive、spark等可以使用OzoneFS API将Ozone作为存储层,而不需要做任务修改

Data Locality – Ozone像HDFS那样对上层应用支持数据本地性。

与HDFS并行部署 – Ozone可以部署在现有的Hadoop集群中, 并且可以与HDFS共享存储磁盘。

架构

在架构上Ozone由三部分组成,分别为Ozone ManagerStorage Container ManagerDatanodes。架构图如下:
OzoneOverview

Ozone Manager(OM)

OzoneManager是一个server服务,主要负责Ozone的namespace,记录所有的volume, bucket和key操作有点类似HDFS的namenode
Ozone由volumes、buckets和Keys组成,其中每个volume是一个namespace的根节点(与HDFS不同,HDFS只提供了一个根节点),所以整个Ozone的namespace是一个volumes的集合或者是一个由类似HDFS那样的树节点组成的森林。这使得OM可以轻松的扩展为多个OM(此功能正在开发)。
OM中也存储了Ozone的一些元数据信息,这些元数据信息包括volumes、buckets和keys,底层通过Ratis扩展元数据的副本数来实现HA

Storage Container Manager(SCM)

类似HDFS中的block manager,是Ozone中一个非常重要的组件,用来管理container的,为OM提供基于block和container的服务
container是由一些block组成的集合,这些block相互之间没有关系。
SCM和数据节点协同工作以维护群集所需的复制级别

关于SCM的作用通过一个使用实例来说明下 – 由客户端调用putKey(keyName, data, pipeline type, replication count)发起一个putKey操作

参数说明
keyName是指文件的名字。data是指要写入的数据。pipeline type指block的副本策略,Ozone目前支持Stand Alone和Ratis两种策略。replication count是指block有多少个副本
一般情况下pipeline type和replication count不用指定,直接使用模式的就行。

整个流程为OM收到putKey请求,向SCM发送一个请求,请求一个包含特定属性的pipeline实例。例如客户端要求Ratis存储策略并且副本数是3,则OM请求SCM返回一个满足此特性的datanode set。如果SCM能够实例化这样一个pipeline(也就是一个datanode set),则将这些dn返回给OM。OM则存储这些信息并将此信息包装成一个元组{BlockID, ContainerName, and Pipeline}。**这里也有点类似HDFS写流程
如果SCM并没有找到一组datanode set来满足clinet的要求,
则SCM创建一个逻辑管道,然后返回它**

从上面的调用过程中可以看出OM与SCM的关系,SCM作为block manager。当client向OM请求datanode set写数据数据时,OM需要向SCM请求block。block从SCM以pipeline的形式返回,此时pipeline是由参与block副本的一组datanode。

SCM主要用来管理blocks、containers和pipelines,为了返回正常可用的pipelines,SCM必须找到node的健康状态,所以SCM也会监听datanode发来的心态,扮演着datanode manager的角色。

SCM内部结构为:
SCM

Block:block数据块对象,真实存储数据的对象,可以拥有多个副本块。
Container:在逻辑上存储的是Block块对象集合。
Pipeline:SCM允许2种Pipeline方式实现多副本:单副本的Standaline模式和多副本的Ratis方式。
Pool:一组特定的数据节点称为一个pool。将节点按pool分组是为了方便日常的维护升级操作,也是为了扩展性的考虑。
Node:物理存储数据的地方。

Datanodes

如果是基于HDFS部署的Ozone也就是Ozone数据节点功能以插件的功能运行在HDFS的datanode中,则就指HDFS的datanode。Ozone也可以单独部署,此时指运行Ozone数据节点的守护进程。DataNode中以Container基本存储单元

Ozone Client

Ozone client在Ozone内部是一个对外开放使用的模块,比如说Ozone相关的shell命令会触发到ozone client,这就是图中显示的Ozone Cli。
Rest Handler是一个钩子,能够做到RPC和Restful通信方式的一键切换。Ozone client能够支持2种方式的通信:RPC方式和Restful接口的方式。
Freon是Ozone内部的性能测试工具。

OzoneFileSysyem

Ozone为了兼容其它框架体系,根据自身独特的数据特点,实现了文件系统接口,称为OzoneFileSystem。这样的话,用户可以以通用的方式来使用Ozone内部的文件对象。在程序上无需做兼容性的改动。

Hadoop Distributed Data Store

上面的架构图中只剩下Hadoop Distributed Data Store没有介绍了,其实Hadoop Distributed Data Store(HDDS)是由Containers、Ratis和SCM组成的,是一个没有全局命名空间的分布式块存储层

DataNodes3个组成一组,每组都是一个Ratis副本链,每个链都可以打开多个containers进行操作。

SCM定期从datanode上接受报告,通知每个节点上打开和关闭的容器副本。基于每次报告的内容制定一些决定,例如如何分配新container、关闭打开的containers和在磁盘/数据丢失时重新复制封闭容器。

SCM Clients可以向SCM请求新块的分配节点,然后将块数据写入分配的容器中。Clients还可以读取open/closed状态的容器,并且可以删除块。关键的一点是, HDDS 并不关心单个容器的内容。内容完全由SCM管理

HDDS细节图如下:
HDDS

部署及测试

Ozone与HDFS结合的话需要基于Hadoop3.0,所以需要先部署Hadoop3.0,具体部署细节在此略去不表。

从官方下载Hadoop3.0和Ozone的安装包(由于官方build的Hadoop3.0中并没有Ozone相关的内容,所以需要单独下载Ozone的安装包),将Ozone的相关内容复制到Hadoop的home目录。命令如下:

1
2
3
4
# 在Ozone的home目录下执行
cp libexec/ozone-config.sh /opt/soft/hadoop/libexec
cp -r share/ozone /opt/soft/hadoop/share
cp -r share/hadoop/ozoneplugin /opt/soft/hadoop/share/hadoop/

利用Ozone的命令生成conf文件,ozone genconf etc/hadoop,此命令会生成ozone-site.xml文件,修改配置之后复制到Hadoop3.0的conf目录中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<configuration>
<property>
<name>ozone.enabled</name>
<value>true</value>
<tag>OZONE, REQUIRED</tag>
<description>
Status of the Ozone Object Storage service is enabled.
Set to true to enable Ozone.
Set to false to disable Ozone.
Unless this value is set to true, Ozone services will not be started in
the cluster.

Please note: By default ozone is disabled on a hadoop cluster.
</description>
</property>
<property>
<name>ozone.om.address</name>
<value>localhost</value>
<tag>OM, REQUIRED</tag>
<description>
The address of the Ozone OM service. This allows clients to discover
the address of the OM.
</description>
</property>
<property>
<name>ozone.metadata.dirs</name>
<value>/opt/hadoop/ozone</value>
<tag>OZONE, OM, SCM, CONTAINER, REQUIRED, STORAGE</tag>
<description>
Ozone metadata is shared among OM, which acts as the namespace
manager for ozone, SCM which acts as the block manager and data nodes
which maintain the name of the key(Key Name and BlockIDs). This
replicated and distributed metadata store is maintained under the
directory pointed by this key. Since metadata can be I/O intensive, at
least on OM and SCM we recommend having SSDs. If you have the luxury
of mapping this path to SSDs on all machines in the cluster, that will
be excellent.

If Ratis metadata directories are not specified, Ratis server will emit a
warning and use this path for storing its metadata too.
</description>
</property>
<property>
<name>ozone.scm.client.address</name>
<value>localhost</value>
<tag>OZONE, SCM, REQUIRED</tag>
<description>
The address of the Ozone SCM client service. This is a required setting.

It is a string in the host:port format. The port number is optional
and defaults to 9860.
</description>
</property>
<property>
<name>ozone.scm.names</name>
<value>localhost</value>
<tag>OZONE, REQUIRED</tag>
<description>
The value of this property is a set of DNS | DNS:PORT | IP
Address | IP:PORT. Written as a comma separated string. e.g. scm1,
scm2:8020, 7.7.7.7:7777.
This property allows datanodes to discover where SCM is, so that
datanodes can send heartbeat to SCM.
</description>
</property>
<property>
<name>ozone.replication</name>
<value>1</value>
</property>

</configuration>

需要将ozone相关的jar引入到classpath中,在user home目录下增加.hadooprc文件

1
2
vim ~/.hadooprc
HADOOP_CLASSPATH=/opt/soft/hadoop/share/hadoop/yarn/*.jar:/opt/soft/hadoop/share/hadoop/tools/*.jar:/opt/soft/hadoop/share/hadoop/ozoneplugin/*.jar:/opt/soft/hadoop/share/hadoop/ozone/*.jar:/opt/soft/hadoop/share/hadoop/mapreduce/*.jar:/opt/soft/hadoop/share/hadoop/hdfs/*.jar:/opt/soft/hadoop/share/hadoop/common/*.jar:/opt/soft/hadoop/share/hadoop/client/*.jar:/opt/soft/hadoop/share/hadoop/yarn/lib/*.jar:/opt/soft/hadoop/share/hadoop/tools/lib/*.jar:/opt/soft/hadoop/share/hadoop/ozoneplugin/lib/*.jar:/opt/soft/hadoop/share/hadoop/ozone/lib/*.jar:/opt/soft/hadoop/share/hadoop/mapreduce/lib/*.jar:/opt/soft/hadoop/share/hadoop/hdfs/lib/*.jar:/opt/soft/hadoop/share/hadoop/common/lib/*.jar:/opt/soft/hadoop/share/hadoop/client/lib/*.jar

如果将Ozone运行在HDFS之上的话,需要在hdfs-site.xml中添加如下内容:

1
2
3
4
<property>
<name>dfs.datanode.plugins</name>
<value>org.apache.hadoop.ozone.HddsDatanodeService</value>
</property>

此时就可以启动相关的服务了,首先启动namenode和datanode,命令为hdfs --daemon start namenodehdfs --daemon start datanode
其次启动scm和om,要先启动scm再启动om,而且在第一次启动的时候要先初始化,命令如下:

1
2
3
4
ozone scm --init
ozone --daemon start scm
ozone om --init
ozone --daemon start om

一切正常就可以在OM的UI上查看信息,OM默认端口上9874,地址为http://omserver:9874/

我们可以运行一些命令来感受下Ozone,
创建一个volume并且查看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
ozone sh volume create --user=work /hive-ozone

ozone sh volume list --user work
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/opt/soft/hadoop-3.2.0/share/hadoop/common/lib/slf4j-log4j12-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/opt/soft/hadoop-3.2.0/share/ozone/lib/slf4j-log4j12-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/opt/soft/hadoop-3.2.0/share/hadoop/ozone/lib/slf4j-log4j12-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]
2019-01-29 15:33:52,786 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
[ {
"owner" : {
"name" : "work"
},
"quota" : {
"unit" : "TB",
"size" : 1048576
},
"volumeName" : "hive-ozone",
"createdOn" : "星期二, 29 一月 2019 07:32:27 GMT",
"createdBy" : "work"
} ]

再来创建一个bucket,ozone sh bucket create /hive-ozone/bucket-test

创建完volume和bucket,就可以上传文件了,也就是创建一个key,Ozone命令为ozone sh key put /hive-ozone/bucket-test/hadoop.log logs/hadoop.log
也可以像hdfs shell那样上传key,命令为ozone fs -put logs/hadoop.log o3fs://bucket-test.hive-ozone/t.log

参考

https://cwiki.apache.org/confluence/display/HADOOP/Building+Ozone
https://hortonworks.com/blog/introducing-apache-hadoop-ozone-object-store-apache-hadoop/
https://hortonworks.com/blog/apache-hadoop-ozone-object-store-overview/
https://hadoop.apache.org/ozone/docs/0.3.0-alpha/index.html
https://hortonworks.com/blog/apache-hadoop-ozone-object-store-architecture/
https://blog.csdn.net/Androidlushangderen/article/details/78168479

您的肯定,是我装逼的最大的动力!