Ozone 介紹

Ozone 是什么

一句話介紹:Ozone 是一個(gè)分布式對(duì)象存儲(chǔ)系統(tǒng),從屬于 Hadoop 生態(tài),支持海量數(shù)據(jù)存儲(chǔ),具有良好的擴(kuò)展性。

為什么需要 Ozone

Hadoop 生態(tài)的默認(rèn)存儲(chǔ)是 HDFS,因此這個(gè)問題也可以理解為:為什么已經(jīng)有 HDFS 這樣成熟的分布式文件系統(tǒng)了,還要再開發(fā)一個(gè)分布式對(duì)象存儲(chǔ)系統(tǒng)?

HDFS 和 Ozone 的對(duì)比

對(duì)比項(xiàng) Ozone HDFS
數(shù)據(jù)模型 OZone是一個(gè)分布式的對(duì)象存儲(chǔ)系統(tǒng),提供的是一個(gè) key-value 形式的對(duì)象存儲(chǔ)服務(wù) HDFS 是典型的樹狀索引結(jié)構(gòu)的文件系統(tǒng)
數(shù)據(jù)獲取 根據(jù) Object 的名稱(key)唯一的獲取該 Object 的內(nèi)容

雖然用戶可以使用類似 test1/test.jpg 這樣的名字,但是這并不表示用戶的 Object是保存在 test1 目錄下面的,對(duì)于 Ozone 來說,test/test1.jpg 僅僅是一個(gè)字符串,和 a.jpg 這種并沒有本質(zhì)區(qū)別,因此,不同名稱的 Object 之間,訪問消耗的資源是類似的
一個(gè)名為 test1/test.jpg 的文件,訪問過程需要先訪問到 test1 這個(gè)目錄,然后再在該目錄下查找名為 test.jpg 的文件
優(yōu)勢(shì) 支持海量的用戶并發(fā)訪問 支持文件的修改(HDFS 僅允許追加寫),支持目錄級(jí)別的操作,比如刪除目錄、重命名目錄、移動(dòng)目錄等非常容易
劣勢(shì) OZone 保存的 Object 不支持修改(追加寫也不行),用戶哪怕僅僅需要修改一個(gè)字節(jié)也需要重新上傳整個(gè) Object 受限于單個(gè)設(shè)備的性能,訪問越深的目錄消耗的資源越大,操作擁有很多文件的目錄也會(huì)很慢

一句話總結(jié)
在云時(shí)代特別是公有云時(shí)代,存儲(chǔ)系統(tǒng)面對(duì)的數(shù)據(jù)規(guī)模急速增長(包括文件個(gè)數(shù)和文件大?。?,傳統(tǒng)的文件系統(tǒng)受限于單個(gè)設(shè)備的能力(例如 HDFS 受限于 NameNode 的內(nèi)存大小和處理速度),和樹狀存儲(chǔ)固有的深層次目錄、海量文件的索引消耗,已經(jīng)不能滿足需求。

在公有云時(shí)代,命名空間扁平化、擴(kuò)展能力更好的對(duì)象存儲(chǔ)成為主流,例如 Amazon S3、阿里云 OSS 等等。

Ozone 和 HDFS 中的一些概念類比

Ozone HDFS
Volum 一級(jí)目錄,如 /volume1
Bucket 二級(jí)目錄,如 /volume1/bucket1
Object 文件,如 /volume1/bucket1/obj1
多級(jí)目錄
ListVolume 獲取一級(jí)目錄列表
ListBucket 獲取二級(jí)目錄列表
PutKey 寫文件
GetKey 讀文件
DeleteKey 刪除文件
修改文件內(nèi)容
修改文件屬性
重命名文件

Ozone 基本架構(gòu)

兩個(gè)工程

上圖中出現(xiàn)了兩個(gè)工程:hadoop-ozone-project 和 hadoop-hdds-project(hdds: Hadoop Distributed Data Store),實(shí)際上,這兩個(gè)工程可以看做分別實(shí)現(xiàn)了 HDFS 中 NameNode 的個(gè)主要功能,在 HDFS 中,NameNode 有兩個(gè)主要功能:

  1. 命名空間(即 FSNameSpace)管理
    即管理 file -> blocks 的映射,在新架構(gòu)下,類似的功能交給 OzoneManager 來負(fù)責(zé),實(shí)現(xiàn)在 hadoop-ozone-project 中。

  2. 存儲(chǔ) block 管理
    即管理 block -> datanodes 的映射,在新架構(gòu)下,類似的功能交給 StorageContainerManager 來負(fù)責(zé),實(shí)現(xiàn)在 hadoop-hdds-project 中。

在 HDFS 中,NameNode 作為核心管理節(jié)點(diǎn),它的擴(kuò)展性比較差,F(xiàn)ederation 的方案實(shí)際使用的也不多,之所以造成這種情況,很大一部分原因就是它負(fù)責(zé)了太多的工作,在新架構(gòu)下,為了提高擴(kuò)展性,把 NameNode 的兩個(gè)核心功能拆分出來,分別放在兩個(gè) project 里去做。

因此,實(shí)際上 hdds 并沒有和 Ozone 綁定在一起,它只是提供了一個(gè)通用的存儲(chǔ)管理層,Ozone 只是它的第一個(gè)用戶而已,NameNode 經(jīng)過改造后,也可以使用 Ozone 作為它的存儲(chǔ)層支持,從而成為 hdds 的第二個(gè)用戶,目前已經(jīng)有相關(guān)的項(xiàng)目在推進(jìn)了。

相關(guān)端口
角色 端口 用途
OM 9874 OzoneManager Http 管理端口
OM 9862 OzoneManager RPC Server 端口
SCM 9860 StorageContainerManager RPC Server 端口
SCM 9861 StorageContainerManager 針對(duì) DataNode 的 RPC Server 端口
SCM 9863 StorageContainerManager 針對(duì) ScmBlockLocationProtocol 協(xié)議的 RPC Server 端口,該協(xié)議被 OM 使用,僅提供 block 的分配和刪除功能
SCM 9876 StorageContainerManager http 管理端口
DN 9880 DataNode 數(shù)據(jù) IO REST 端口
DN 9858 DataNode 數(shù)據(jù) IO RPC 端口

Ozone 中的核心概念

hdds 中的幾個(gè)核心概念

1. StorageContainerManager
作為 hdds 中的管理角色,它以獨(dú)立進(jìn)程的形式運(yùn)行,需要管理所有 DataNode 上報(bào)的 container 信息,定期處理所有 DataNode 的心跳,并且還要響應(yīng)來自 OzoneManager 的 RPC 請(qǐng)求(例如分配新的 block 等等),SCM 管理的數(shù)據(jù)主要包括每個(gè) container 中的 block 信息以及每個(gè) container replicate 在哪幾個(gè) DataNode 上等等,這些元信息都以本地?cái)?shù)據(jù)庫的形式保存(默認(rèn) RocksDB,可選 levelDB)。

2. DataNode
在 hdds 中,數(shù)據(jù)依然保存在 DataNode 上,每個(gè) DataNode 上都需要運(yùn)行一個(gè)相應(yīng)的進(jìn)程(類似于 HDFS 中的 DataNode 進(jìn)程)來提供服務(wù),目前這個(gè)進(jìn)程名字叫做 HddsDatanodeService,它有兩個(gè)職責(zé):

  1. 向 SCM 注冊(cè)自己,定期上報(bào)心跳,并接受 SCM 的管理。
  2. 和 client 之間,以 chunk 為單位進(jìn)行數(shù)據(jù)讀寫。

3. container
hdds 中,DataNode 的基本切割單元變成了 container,默認(rèn)大小為5G,這是一個(gè)更大粒度的劃分,同時(shí)在 DataNode 之間也以 container 為單位進(jìn)行多副本復(fù)制,DataNode 向 SCM 上報(bào)的基本單元也變成了 Container,這樣一來,就大大的減少了 SCM 的管理壓力(相對(duì)于 HDFS 中默認(rèn)128M的管理粒度)。

4. block
container 又會(huì)劃分為多個(gè) block,在 OZone 中,和 HDFS 一樣,文件也要被切割為一個(gè)個(gè)的 block,其中,文件的第一個(gè) block 最大為 128M,后續(xù)的 block 最大為 256M。每當(dāng) Ozone 需要一個(gè)新的 block 時(shí),都需要向 SCM 申請(qǐng)。

5. chunk
無論是5G 的 container,還是 256M 的 block,都不能作為 client 與 DataNode 之間的 IO 單位(因?yàn)榱6忍罅耍?,client 和 DataNode 之間進(jìn)行 IO 的單位是 chunk,默認(rèn)大小是 16M。

每一個(gè) container 都需要保存自己目前寫入了多少 chunk,每個(gè) chunk 的名字、實(shí)際長度等信息也需要記錄,這些元信息都以 RocksDB 的形式保存在每個(gè) container 的存儲(chǔ)目錄下面,換句話說,在 hdds 中,container 自己就是一個(gè)縮小版的對(duì)象存儲(chǔ)系統(tǒng)。

6. pipeline
pipeline 是一組 DataNode 的集合,假如系統(tǒng)配置三副本,那么一個(gè) pipeline 就是三個(gè) DataNode 的集合,每一個(gè) container 都需要搭配一個(gè) pipeline 來完成數(shù)據(jù)的寫入和讀取。

在 OZone 中,每個(gè) DataNode 只能屬于一個(gè) Pipeline,假如系統(tǒng)是三副本并且只有三個(gè) DataNode,那么實(shí)際上也就只存在一個(gè) Pipeline,所有 container 都需要搭配這唯一的一個(gè) pipeline 進(jìn)行讀寫操作。

Ozone 中的 pipeline 相比 HFDS 中簡(jiǎn)單了不少,以默認(rèn)的 RaftPipeline 為例,使用這種 PipeLine 寫入和讀取時(shí),都按照 Raft 協(xié)議的讀寫方式來,即:


  1. 客戶端將數(shù)據(jù)發(fā)送給 pipeline 中的 leader dn,leader dn 再將數(shù)據(jù)分發(fā)給所有的 follower dn,只有能達(dá)到大多數(shù)寫成功,就認(rèn)為此次寫成功。


  2. 客戶端直接從 pipeline 中的 leader dn 讀取數(shù)據(jù)。

顯而易見,這種方式可以很好的保證強(qiáng)一致性,使得 client 時(shí)刻能讀到最新的數(shù)據(jù),但是,讀寫都需要經(jīng)過 leader dn 顯然也會(huì)增大 leader 的壓力(可以參照 ceph 中的 leader osd 做個(gè)類比)

Ozone 的幾個(gè)概念

1. OzoneClient
類似于 HDFS 中的 DFSClient,是 Ozone 存儲(chǔ)系統(tǒng)的客戶端,目前,Ozone 提供 RPC 客戶端和 REST 客戶端,有相應(yīng)的工廠方法獲取對(duì)應(yīng)的實(shí)現(xiàn)類。

2. OzoneManager
如上文所述,OzoneManager 負(fù)責(zé)命名空間管理工作,它負(fù)責(zé)的是一個(gè) key -> blocks 的映射,以及 block 分配、刪除等等工作,注意在 Ozone中,一個(gè) block 和 必須從屬于一個(gè) container,他們有很強(qiáng)的綁定關(guān)系,即 blockId = containerId + localId,其中 localId 是一串隨機(jī)字符。

OzoneManager 的元數(shù)據(jù)也以 rocksDB 的形式保存。

OZone 中典型操作時(shí)序圖

兩個(gè)前提

  1. 各個(gè)組件之間的 RPC 交互中,數(shù)據(jù)序列化使用 ProtoBuf,RPC 框架使用 gRPC,底層傳輸框架使用 netty,協(xié)議 http。
  2. 本文中的 client 特指 rpc client,使用 ozone 命令行時(shí)都是這個(gè)類型的 client,client 和 DataNode 之間的數(shù)據(jù)存取,同樣是 Protobuf + gRPC + netty。

createVolume

listVolume

deleteVolume

createBucket

listBucket

deleteBucket

putKey

  1. 整個(gè)流程中,最重要的一步就是 allocateBlock,這是由 SCM 完成的,SCM 分三步來做這件事情:

    1. 找到一個(gè)可用的 pipeline

      1. 如果系統(tǒng)中有空余的 DataNode,那么優(yōu)先選擇空余的 DataNode,注意一個(gè) DataNode 只能屬于一個(gè) pipeline。
      2. 如果沒有,則選擇一個(gè)現(xiàn)有的 pipeline(Round-Robin方式)
    2. 在該 pipeline 下,找到一個(gè)可用的 container

      1. 首先查看有沒有預(yù)分配的 container 可用,SCM 默認(rèn)一次分配 20 個(gè) container。
      2. 如果沒有,再看有沒有正在寫入的 container 可用,一個(gè) container 寫滿 5G 后就會(huì)被關(guān)閉。
      3. 如果還沒有,則新分配 20 個(gè) container,返回其中一個(gè)。
    3. 從該 container 中分配一個(gè) block

  2. OM 向 SCM 申請(qǐng) block 時(shí),需指定這個(gè) block 的 size,size 最大容量按照如下方式確定:

    1. 如果該 block 是文件的第一個(gè) block,則其最大容量為 128M。
    2. 如果該 block 不是文件的第一個(gè) block,則其最大容量為 256M.
  3. client 向 DataNodes 寫數(shù)據(jù)時(shí)

    1. IO 單位為 chunk,默認(rèn)大小 16M。
    2. 通過 container 關(guān)聯(lián)的 pipeline 寫入,默認(rèn)使用 Raft pipeline,傳輸層是 protobuf + gRPC + netty, Raft Pipeline 寫入流程:
      1. client 將數(shù)據(jù)發(fā)送給 leader,一開始 client 并不知道 leader 是誰,因此會(huì)隨機(jī)挑選一個(gè) pipeline 中的 DataNode 發(fā)送數(shù)據(jù),對(duì)方會(huì)回復(fù)他真正的leader 地址,接著 client 再重發(fā)一次,發(fā)給真正的 leader。
      2. leader 收到數(shù)據(jù)后,需要將數(shù)據(jù)分發(fā)給所有的 follower,只要能達(dá)到大多數(shù),就認(rèn)為此次寫入成功。
      3. leader 回復(fù) client 寫入成功。
      4. client 并沒有從零開始實(shí)現(xiàn)上面的 Raft 寫入流程,而是集成了 Apache Ratis 這個(gè)項(xiàng)目,這是一個(gè) Raft 協(xié)議的 Java 實(shí)現(xiàn),Ozone 直接使用了它。

getKey

  1. 讀取時(shí)存在預(yù)讀機(jī)制,即 client 總是以 chunk 為單位從 DataNodes 讀取數(shù)據(jù)。
  2. 讀取時(shí),client 直接從 leader dn 讀取數(shù)據(jù)。

deleteKey

可以看到,deleteKey 是一個(gè)異步過程,client deleteKey 返回成功并不代表數(shù)據(jù)已經(jīng)從 DataNode 上刪除。

  1. OM 上有一個(gè)后臺(tái)刪除線程,定期掃描 OM DB,找出需要?jiǎng)h除的 key,將 key 和相關(guān)的 block 發(fā)送給 SCM 進(jìn)行刪除。
  2. SCM 在追加一條本地刪除日志,并且改寫 SCM DB 后,向 OM 返回成功。
  3. SCM 上也有一個(gè)后臺(tái)線程,定期掃描刪除日志,并生成針對(duì)各個(gè) DataNode 的刪除 block 命令。
  4. SCM 上的心跳線程接收各個(gè) DataNode 的心跳,并在回復(fù)中帶上刪除 block 命令,DN 收到命令后,真正刪除數(shù)據(jù)。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請(qǐng)通過簡(jiǎn)信或評(píng)論聯(lián)系作者。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容