HDFS對象存儲--Ozone架構設計


前言


如今做雲存儲的公司非常多,舉2個比較典型的AWS的S3和阿里雲.他們都提供了一個叫做對象存儲的服務,就是目標數據是從Object中進行讀寫的,然后能夠通過key來獲取相應的Object,就是所謂的key-object的存儲.這種優點就在於用戶使用起來非常方便的,不須要走冗雜的操作流程.可是本文所要闡述的則是HDFS中的對象存儲,對於這種需求,Hadoop作為一套完好的分布式系統,當然也要與時俱進,在HDFS-7240中進行了實現,眼下此功能真在開發中,名叫Ozone,內部有非常多的概念與業界的都是相似的,比如Bucket,Object等.下面是本人對於Ozone設計文檔的一個譯文,可能會有翻譯不到位的地方,附上原文鏈接:Ozone-architecture-v1.pdf

文件夾


  1. 介紹
    1.1 基本要求
    1.2 大小要求

  2. 高層次設計
    2.1 與HDFS共享Datanode Storage存儲
    2.2 Storage Container存儲容器
    2.3 Storage Container Identifier存儲容器標志符
    2.4 Storage Container存儲容器服務的調用
    2.5 Datanode中的Ozone Handler
    2.6 Storage Container Manager存儲容器管理器

  3. 詳細實現
    3.1 對象鍵值到存儲容器的映射
    3.2 范圍分區Vs哈希分區
    3.3 bucket到存儲容器的映射
    3.4 Storage Container存儲容器的要求
    3.5 Storage Container存儲容器實現要點
    3.6 Pipeline數據一致性

  4. 未來工作
    4.1 Ozone API
    4.2 集群層級API
    4.3 Storage Volumes層級API
    4.4 Bucket層級API
    4.5 Object層級API

  5. 引用

介紹


Ozone提供了一個key-object鍵值-對象存儲的服務,相似AWS的S3服務. Key和Object對象是隨機的字節數組.單個key的大小期望是小於1k,可是values對象能夠從小到幾百字節大到幾百兆.鍵值/對象被組織進了bucket的概念中.一個bucket擁有唯一的key集合.Bucket存在於Storage-Volume中,而且在Storage-Volume中擁有唯一的名字.一個storage volume擁有全局唯一的名字.更近一步的說,storage volume對buckets和存儲的數據有配額上的限制.在私有雲中,它能夠被用來創建給用戶(比如home文件夾),project項目,或者租有者.管理員能夠分配一定配額限制的私有storage volume給個體用戶或者公有的共享storage volume.在公有雲中,多storage volume能夠以獨立的配額分配在每一個雲中.
一個bucket被2部分名字的組合唯一標識: storage-volumeName/bucketName.一個對象的名字被storage-volumeName/bucketName/objectKey 3部分所標識.
我們的模式相似於Azure Blob Storage(WASB).他們的bucket在每一個帳戶中是唯一的.可是,我們用storage volume來代替了這個帳戶概念.因此相比之下,S3的bucket在全部帳號中保持唯一.
數據的組織結構能夠下面面的圖形進行展示.
這里寫圖片描寫敘述

基本要求


Ozone中主要的操作例如以下(API方法在文檔尾部將會給出):

  • 管理員創建Storage Volume.
  • 創建/刪除 buckets.每一個bucket擁有一個獨立的URL.Buckets不能被重命名.僅僅有storage volume的所屬者或所屬組才干創建/刪除volume中的bucket.
  • 在一個storage volume中列出buckets列表.
  • 依據給定的key在bucket中創建/刪除object對象.對象的數據或值能夠流式的傳輸到Ozone服務中.當對象被寫滿的時候將僅僅會同意讀操作.同一時候不保證對象的局部寫.
  • 列舉出bucket的內容
  • 創建/更新/刪除 buckets的ACL訪問控制列表

大小要求


本節列舉了少部分的限制值來詳細化一些要求.下面是目標版本號1的一些指標:

  • Storage Volume名字: 3~64字節
  • Bucket 名稱: 3~64字節
  • Key大小: 1KB
  • Object大小: 5G
  • 系統總buckets數量: 1000w
  • 每一個bucket中對象數量: 100w
  • 每一個storage volume中的bucket數: 1000

Ozone元數據包括下面內容:

  • Storage Volume層級元數據
    • Storage volume所屬者
    • Storage Volume名稱
  • Bucket層級元數據
    • Bucket所屬者: 擁有此bucket中數據的所屬用戶.
    • Bucket ACL訪問控制信息
    • 全局唯一的Bucket名稱
    • Bucket Id: 與bucket相關的系統產生的數字型的標識

高層級設計


與HDFS共享Datanode數據存儲


DataNode同一時候為HDFS和Ozone存儲數據.Ozone的數據用的是獨立的blockPool並擁有獨立的blockPool Id.也就是說能夠同一時候存在多種volume命名空間,每一個volume有屬於自己的block pool.相同的能夠同一時候存在多個獨立的Ozone命名空間在所屬的block pool下.一個DN能夠同一時候存儲多個HDFS和Ozone的block pool.此關系結構例如以下圖所看到的:
這里寫圖片描寫敘述

Storage Container容器


一個storage container從概念上來說,指的是用來存儲Ozone數據(就是bucket中的數據)和Ozone元數據的一個存儲單元.Storage container與HDFS的block一樣,共同存儲於DataNode上.可是與HDFS不同的一點,Ozone沒有一個相似於NameNode的中心節點,相反地,他是一個分離的元數據的存儲.這些元數據分布式的存在於各個storage container中.每一個storage container以whole的形式存在(相似於HDFS中的block).我們對container副本的成功操作保證了強一致性.Storage container的最大值的大小取決於他的副本復制能力以及從節點故障中恢復的能力.最大值的大小是可配的,可是他至少要大於一個簡單對象所同意的最大值.

一個bucket能夠擁有百萬數量級的對象而且在存儲的大小級別上能夠達到T級別,這遠遠大於一個storage container.因此一個bucket會被分為非常多partion分區,每片分區會存儲在一個container中.(一個storage container能夠包括最大值數量的的分區,然而對象僅僅能來自一個bucket.)在我們的初始設計實現中,一個object對象是全然存在於一個單一的container中,這么做后面可能會輕松一些.

Storage container是靠DataNode來實現的(用戶能夠通過配置來禁用此功能假設用戶僅僅須要使用HDFS的block功能).本節定義了storage container的一些語義和要求.Storage container須要存儲下面多種類型的數據,每類數據有稍微不同的語義:

  • Bucket元數據

    • 個體單元的數據是非常小的-kb級別.每一個storage container能夠保存上百萬bucket的元數據.
    • 這點要求能夠更新,由於一個bucket的ACL是能夠被更新的,而且要能保證操作的原子性.
    • 滿足主要的Get/Put的API設計已經足夠.
    • 在container中能運行列表操作以便展示全部的bucket.
  • Bucket數據

    • Storage container須要能夠存儲小到幾百kb大到上百mb的對象數據.
    • 對象須要通過對象的key進行訪問(所以container存儲數據也必須包括存儲對象的索引).
    • 必須能支持個體對象讀寫的流式API.
    • 數據中的對象不支持追加寫以及原地更新.

在后面的小節,我們將闡述DataNode怎樣實現storage container來達到以上的要求.

Storage Container標識符


每一個storage container都被獨立的storage container標識符所獨立標識.它是一個邏輯上的獨立標識(相似於HDFS中的blockId)而且不包括真正意義上container的網絡位置.

對象的key會映射到storage container標識符.這個標識符會傳入storage container manager管理器去定位包括目標對象container所在的DataNode.相似的,bucket的名稱也會映射到storage container標識符,這個container保存有bucket的元數據.在后面的小節中,我們會詳細提到這個映射關系是怎樣實現的.Storage container標識符是64位的,相似於hdfs中的block id.在未來,我們將把它擴展到128位.可是那將會是一個大的改變,由於我們想盡可能的復用hdfs的block管理器相關的代碼.

Storage Container Service中的過程調用


下面的圖形展示了Ozone中的典型過程調用,當中主要包括了Storage Container Service服務和Ozone Handler處理器:
這里寫圖片描寫敘述

DataNode中的Ozone Handler


Ozone handler是Ozone中的模塊組件,被DataNode所持有並對外提供Ozone服務.Handler包括了一個http server並實現了Ozone REST方式API.Ozone Handler與storage container manager管理器交互來查詢container的位置.與DataNode中的storage container交互實現不同的操作.這個功能組件能夠被禁用假設用戶僅僅想要使用HDFS而不須要Ozone功能.

Storage Container Manager管理器


Storage container manager管理器非常相似於HDFS中block manager中的管理功能.Storage container manager管理器從各個DataNode中收集心跳,處理storage container的報告並跟蹤每一個storage container的位置.他包括了一個storage container映射圖,以此提供了前綴匹配的方式去查詢storage container.之前提到過DN能夠同一時候存儲HDFS和Ozone的數據.Ozone的數據所屬的是分離的block pool而且用的是Storage container manager管理器提供的分離的blockPool Id.圖形展示效果例如以下.我們計划盡可能的復用NameNode已有的block管理部分的代碼實現來實現container的管理.我們相同能夠復用DataNode 中block pool service服務的實現代碼.
這里寫圖片描寫敘述

詳細實現


映射object-key到storage container

在我們的設計中,我們計划使用哈希分區的模式來映射key到他所存儲的storage container.Key的值是被哈希計算的,同一時候會帶上bucketId的前綴.結果值通過前綴匹配能夠映射到storage container.當container逐漸變大,我們會對此進行切割,並用擴展哈希算法又一次映射key到相應container的映射關系.Storage container manager管理器會存儲這些映射關系到前綴樹中以此實現高效的前綴匹配.每一個bucket都有屬於自己的前綴樹.

范圍分區 vs 哈希分區


在數據庫和對象存儲中,范圍分區是另外一項比較受歡迎的用來對key進行分區的技術.下面是2個技術的簡短的比較.我們偏向於使用哈希分區的方法,由於它相比較能更簡單的去實現而且能滿足我們的需求.

  • 范圍分區模式須要范圍索引.范圍索引相同非常巨大而且須要分布式的存儲.這復雜化了切割多個分區的操作,由於他額外須要索引的更新.
  • 范圍分區在搜索過程中多引進了一種額外的跳躍,當第一次范圍索引須要去讀.
  • 范圍分區相同有熱點問題.相似名字的key會造成相同范圍內的大並發量的訪問.
  • 然而,范圍分區提供了有序訪問以及有序列表展示的優勢.可是我們覺得對於一個對象存儲而言,一個有序的訪問並非一個重要的要求.列表有序的展示能夠在后面的階段內用二級索引的方式來實現.我們相同相信對於眼下的設計而言是足夠靈活的,假設我們在未來想要對此加入范圍索引的話.

映射bucket到storage container


Bucket的元數據相同存儲在storage container中.Bucket的名字是被用來作為key做哈希計算的.多個bucket的元數據能夠存在於storage container中.我們在全部與storage container關聯的bucket中設計了一個特殊的bucketId,bucketId前綴中會帶上container Id.

Storage Container要求


Storage Container存儲在各個DataNode上.對於Storage Container我們有下面的要求:

  • Storage Container能夠可靠地被復制.
  • Storage Container保持嚴格的一致性.
  • Storage Container對於內部存儲的對象能提供高效的鍵值對的查詢方式.
  • Storage Container必須能夠以流式的方式對object進行讀寫操作.
  • Storage Container必須能夠支持get/put接口,來存儲和更新bucket元數據.
  • Storage Container對於內部存儲的bucket必須能提供一個原子的更新操作.
  • Storage Container能夠進行分裂當他們達到一定限制大小的時候.

Storage Container的實現要點


  • 我們傾向於盡可能的復用HDFS現有的block pool管理方面的功能代碼.因此我們會將StorageContainer作為Block類的擴展類.一個hdfs block由一個標識符,生成時間記錄和大小組成.這3個屬性相同能夠應用到storage container中.
  • 為了保證一致性和持久性,storage container實現了少量的原子性和持久化的操作,比方事務.Container對這些操作提供了可靠的保證.在第一階段中,我們實現下面事務操作:
    • Commit: 這個操作促進了對象從被寫到最后的確認結束.一旦這個操作成功,這個container就會保證對象是可讀的.
    • Put: 這個操作適用於小規模的寫操作,比如元數據的寫動作.
    • Delete: 刪除對象.
  • Container中的每一個事務會有一個事務ID,而且必須被持久化.
  • 我們計划為storage container實現一個新的data-pipeline,由於他要求一個不同類型的更新和恢復語義操作.在下一小節中我們會給出data-pipeline的設計概述.
  • 我們正在考慮利用leveldbjni來作為storage container的原型設計,leveldbjni正好能滿足我們storgae container鍵值對存儲的需求.

Data Pipeline一致性

Data-Pipeline管道鏈流式復制副本數據到container中.Container的副本也有產生記錄相似於HDFS的block.每一個pipeline副本的標記記錄在pipeline創建的時候會被更新,所以不論什么舊的container會被撤銷.HDFS在block恢復的時候額外使用了block length副本長度來推斷副本是否已經更新到最新.相似地, storage container用了事務ID來推斷container副本是最新的.很多其它的pipeline設計細節將會上傳到相應hdfs jira上.

未來工作


我們並沒有在文檔中細致闡述下述的要求,可是我們將會在后面階段的工作中實現這些功能:

  • High availability: 高可用性,Storage container manager管理器須要是高可用的服務.一個解決方式是利用HDFS Journal的QJM機制實現Active/Standby的方式.第二種方式做成全部Active的服務配上Paxos環的方式.我們會在第二階段的工作中對這個問題進行社區內的討論.
  • Security: 安全,我們能夠利用HDFS的kerberos認證機制
  • Cross cool replication: 跨類型副本拷貝,我們將會使用一種對HDFS和Ozone都有利的方式去實現這個功能.

Ozone API


Cluster層級APIs

  • PUT StorageVolumes
    • API - PUT /admin/volume/{StorageVolume}
      • 創建一個storage volume
      • 僅僅有管理員才同意調用這個操作
  • HEAD StorageVolume
    • API - HEAD /admin/volume/{StorageVolume}
      • 檢測Storage Volume是否存在
      • 僅僅有管理員才干調用這個操作
  • GET
    • 列出集群中全部的Storage Volume.
  • DELETE Storage Volumes
    • API - DELETE /amin/volume/{StorageVolume}
      • 刪除一個volume假設他是空的

Storage Volume層級APIs


  • GET Buckets
  • API - GET /
    • 利用用戶的認證信息登錄
    • 返回請求發送者所擁有的buckets列表
  • Get User Buckets
    • API - GET /admin/user/userid
      • 利用用戶認證信息進行登錄, 假設他/她有權限閱讀其它用戶的信息,返回那個用戶所獨有的buckets列表信息.

Bucket層級API

  • LIST objects in a bucket
    • API - GET/{bucketName}
      • 返回buckets中最多1000個數量的對象key
  • PUT bucket
    • API - PUT/{bucketName}
      • 為請求發送者創建bucket
    • GET/PUT Bucket ACL
      • API - /{Bucket}?acl
      • 同意用戶獲取/設置bucket的ACL
  • HEAD bucket
    • API - HEAD/{bucketName}
    • 檢查bucket是否存在,前提是請求發送者有權限訪問此bucket
  • DELETE bucket
    • API - DELETE/{bucketName}
      • 刪除bucket假設此bucket為空的話

Object層級APIs

  • GET object
    • API - GET/{bucketName}/{key}
      • 返回給定key所代表的對象值,假設這個值存在
      • 在第一階段暫不支持ACL,因此僅僅有所屬用戶才干讀寫自身的bucket.
  • PUT object
    • API - PUT/{bucketName}/{key}
      • 在bucket中創建一個對象
      • 在第一階段暫不支持ACL,因此僅僅有所屬用戶才干讀寫自身的bucket.
      • 不支持局部的上傳,僅僅有對象全部上傳成功了才被覺得是一次成功的操作.
  • HEAD object
    • API - HEAD/{bucketName}/{key}
      • 檢測對象是否存在
      • 在第一階段僅僅有bucket的所屬用戶才干調用此操作
  • DELETE object
    • API - DELETE/{bucketName}/{key}
      • 刪除對象

引用


1.Extendible Hashing(擴展哈希算法)-
http://en.wikipedia.org/wiki/Extendible_hashing
2.leveldbjni - A Java Native Interface(Java本地接口) to
LevelDB. https://github.com/fusesource/leveldbjn


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM