【HBase】HBase工作原理

HBASE原理

一、原理

1、物理存儲

1.hregion

    hbase表中的數據按照行鍵的字典順序排序,hbase表中的數據按照行的的方向切分爲多個region。

    最開始只有一個region隨着數據量的增加,產生分裂,這個過程不停的進行。一個表可能對應一個或多個region。

    region是hbase表分佈式存儲和負載均衡的基本單元,一個表的多個region可能分佈在多臺HRegionServer上。

2.Store

    region是分佈式存儲的基本單元,但不是存儲的基本單元,其內部還具有結構。一個region由多個Store來組成。

    有幾個store取決於表的列族的數量,一個列族對應一個store。之所以這麼設計,是因爲一個列族中的數據往往數據很類似,方便進行壓縮,節省存儲空間。

3.memStore

    表的一個列族對應一個store,store的數量由表中列族的數量來決定。一個store由一個memstore和零個或多個storefile組成。

    memStore負責保存內存中的數據。

4.Storefile

    storefile其實就是hdfs中的hfile只能寫入不能修改,所以hbase寫入數據到hdfs的過程其實是不斷追加hfile的過程。

    hfile的結構:

HFile分爲六個部分:

    Data Block段–保存表中的數據,這部分可以被壓縮

    Meta Block 段(可選的)–保存用戶自定義的kv對,可以被壓縮。

    File Info段–Hfile的元信息,不被壓縮,用戶也可以在這一部分添加自己的元信息。

    Data Block Index段–Data Block的索引。每條索引的key是被索引的block的第一條記錄的key。

    Meta Block Index段(可選的)–Meta Block的索引。

    Trailer–這一段是定長的。保存了每一段的偏移量,讀取一個HFile時,會首先 讀取Trailer,Trailer保存了每個段的起始位置(段的Magic Number用來做安全check),然後,DataBlock Index會被讀取到內存中,這樣,當檢索某個key時,不需要掃描整個HFile,而只需從內存中找到key所在的block,通過一次磁盤io將整個 block讀取到內存中,再找到需要的key。DataBlock Index採用LRU機制淘汰。

    HFile的Data Block,Meta Block通常採用壓縮方式存儲,壓縮之後可以大大減少網絡IO和磁盤IO,隨之而來的開銷當然是需要花費cpu進行壓縮和解壓縮。

    目標Hfile的壓縮支持兩種方式:Gzip,Lzo。

5.HLog(WAL log)

    WAL意爲Write ahead log(http://en.wikipedia.org/wiki/Write-ahead_logging),類似mysql中的binlog,用來做災難恢復之用,Hlog記錄數據的所有變更,一旦數據修改,就可以從log中進行恢復。

    每個Region Server維護一個Hlog,而不是每個Region一個。這樣不同region(來自不同table)的日誌會混在一起,這樣做的目的是不斷追加單個文件相對於同時寫多個文件而言,可以減少磁盤尋址次數,因此可以提高對table的寫性能。帶來的麻煩是,如果一臺region server下線,爲了恢復其上的region,需要將region server上的log進行拆分,然後分發到其它region server上進行恢復。

    HLog文件就是一個普通的Hadoop Sequence File,Sequence File 的Key是HLogKey對象,HLogKey中記錄了寫入數據的歸屬信息,除了table和region名字外,同時還包括 sequence number和timestamp,timestamp是”寫入時間”,sequence number的起始值爲0,或者是最近一次存入文件系統中sequence number。HLog Sequece File的Value是HBase的KeyValue對象,即對應HFile中的KeyValue。

2、讀寫流程

1.hbase寫入數據

    數據寫入hbase時,先在hlog中記錄日誌,再修改memstore,然後直接返回成功。這樣不需要真正等待寫入hdfs的過程,所以很快。

    memstore內存有限,當寫入數量達到一定的閾值的時候,就會創建一個新的memstore繼續工作,而舊的memstore會用一個單獨的線程將數據寫出到storefile中,最終清空舊的memstore並在zookeeper中記錄最後寫出數據時間的redo point信息。

    由於storefile不能修改,所以數據的更新其實是不停創建新的storefile的過程。

    這樣多個storefile中可能存在對同一個數據的多個版本,其中部分舊的版本其實是垃圾數據,時間過長,垃圾數據就可能很多,浪費磁盤空間。

    所以當達到一定的閾值的時候,master會自動合併storefile,在合併的過程中將垃圾數據清理。而當合並出來的文件達到一定程度時,再從新進行切分,防止文件過大。

    雖然看起來是小變大再變小,但是經過這個過程垃圾數據就被清理掉了。所以store中的數據,其實是memstore和storefile來組成的。

    而memstore由於是內存中的數據,一旦斷電就會丟失。爲了解決可能的意外造成數據丟失的問題,hbase在整個hregionserver中,通過記錄hlog來保存了所有數據操作的記錄。當hbase啓動時,會檢查zookeeper中的redopoint信息,從hlog中恢復這個時間點之後的數據,解決內存中memStore數據容易丟失的問題。

    hlog文件在每臺hregionServer中都有一個,所有這臺機器中的所有HRegion都公用這個文件,這樣整個機器的磁盤性能都可以爲這一個文件提供支持,提升文件的讀寫效率。

    hlog文件也是存儲在hdfs中的,也是分佈式存儲的,保證了日誌文件的可靠性。

2.hbase讀取數據

    在查詢數據時,先查找內存,如果內存中有當前鍵對應的數據,獲取數據直接返回。

    如果沒有在內存中找到數據,就去查找region對應的hfile,注意不是將所有hfile中的數據恢復到內存,而是查找每個hfile的Trailer,通過trailer找到Data Block Index,如果在這裏發現了要找的數據,通過索引找到Data Blocks中對應的Data Block,將Data Block數據送回內存組裝,最終將多個hfile中獲取到的數據進行合併,然後返回最新版本的數據。

    由於hbase中的數據天然排序,再加上底層索引,整個查詢也可以非常的快。

3.hbase中region的尋址

    在hbase的hbase名稱空間下有一張meta表,其中存放了表和region和regionSever之間的對應關係信息,這個表很特別,規定meta表只能有一個region。並且這個meta表的這個region的位置信息被存放在了zookeeper的meta-region-server節點下。

    在客戶端從hbase中查找數據時,需要先聯繫zookeeper找到meta表對應的region的位置,連接這個位置讀取到meta表中的信息,才能知道要查詢的表、表的region和region對應的regionServer的信息。再根據這些信息連接真正要查詢的表對應的region的regionServer進行讀取,這個過程就稱之爲region的尋址過程。

    這樣的尋址過程是相當耗費時間的,爲了提高性能,客戶端通常會緩存之前已經知道的region尋址信息,當客戶端再次讀取同一個表中的數據時,可以通過本地緩存的region地址信息,直接定位讀取,提高效率。

 

3、存儲系統三種結構

1.hash存儲

    哈希存儲引擎是哈希表的持久化實現,支持增、刪、改以及隨機讀取操作,但不支持順序掃描,對應的存儲系統爲key-value存儲系統。對於key-value的插入以及查詢,哈希表的複雜度都是O(1),明顯比樹的操作O(n)快,如果不需要有序的遍歷數據,哈希表就是your Mr.Right。

2.B樹

    B+樹 B-樹 B*樹

    B樹存儲引擎是B樹的持久化實現,不僅支持單條記錄的增、刪、讀、改操作,還支持順序掃描(B+樹的葉子節點之間的指針),對應的存儲系統就是關係數據庫(Mysql等)。

3.LSM樹

    LSM樹(Log-Structured Merge Tree)存儲引擎和B樹存儲引擎一樣,同樣支持增、刪、讀、改、順序掃描操作。而且通過批量存儲技術規避磁盤隨機寫入問題。當然凡事有利有弊,LSM樹和B+樹相比,LSM樹犧牲了部分讀性能,用來大幅提高寫性能。

    通過以上的分析,應該知道LSM樹的由來了,LSM樹的設計思想非常樸素:將對數據的修改增量保持在內存中,達到指定的大小限制後將這些修改操作批量寫入磁盤,不過讀取的時候稍微麻煩,需要合併磁盤中歷史數據和內存中最近修改操作,所以寫入性能大大提升,讀取時可能需要先看是否命中內存,否則需要訪問較多的磁盤文件。極端的說,基於LSM樹實現的HBase的寫性能比Mysql高了一個數量級,讀性能低了一個數量級。

    LSM樹原理把一棵大樹拆分成N棵小樹,它首先寫入內存中,隨着小樹越來越大,內存中的小樹會flush到磁盤中,磁盤中的樹定期可以做merge操作,合併成一棵大樹,以優化讀性能。

 以上這些大概就是HBase存儲的設計主要思想,這裏分別對應說明下:

    因爲小樹先寫到內存中,爲了防止內存數據丟失,寫內存的同時需要暫時持久化到磁盤,對應了HBase的MemStore和HLog。

    MemStore上的樹達到一定大小之後,需要flush到HRegion磁盤中(一般是Hadoop DataNode),這樣MemStore就變成了DataNode上的磁盤文件StoreFile,定期HRegionServer對DataNode的數據做merge操作,徹底刪除無效空間,多棵小樹在這個時機合併成大樹,來增強讀性能。

4、hbase系統架構:

    hbase中的老大叫hmaster,小弟叫hregionServer,客戶端叫Client,Zookeepr爲hbase提供集羣協調。


 

1.client

    訪問hbase保留一些緩存信息提升效率。

2.zookeeper

    保證任何時候集羣只有一個HMaster。

    監控regionServer的狀態,將其上線下線信息通知mater。

    存儲meta表Region的地址。

    存儲hbase的元數據信息。包括有哪些表、有哪些列族等等。

3.Master

    爲RegionServer分配Region。

    爲RegionServer進行負載的均衡。

    GFS上的垃圾回收。

    處理對Schema數據的更新請求。

4.RegionServer

    維護Master分配給它的region,處理對這些region的IO請求。

    負責切分在運行過程中變得過大的region。

5、總結

1.爲什麼hbase可以很快

1>從邏輯結構上來說

    表按照行鍵進行了排序,而且加了索引,所以查詢時可以很快定位。

    數據按照行鍵切分爲多個HRegion,分佈在多個RegionServer中,查詢大量數據時,多個RegionServer可以一起工作,從而提高速度。

2>從物理結構上來說

    HRegion是存活在RegionServer的內存中的,讀寫會非常的高效。

    還有HFile的支持保證大量的數據可以持久化的保存。

    數據最終落地到HDFS中,分佈式的存儲,保證數據段可靠性和可擴展性。

2.爲什麼hbase可以存儲很多數據

    基於hdfs,所以支持可擴展性,可以通過增加大量的廉價的硬件提高存儲容量。

    按列存儲,空的數據不佔用空間,當存儲稀疏數據時,不會浪費空間。

    按例存儲,同一列的數據存放在一起,而同一列的數據一般都是同樣的類型的內容相似的數據,可以實現非常高效的壓縮,節省空間。

3.爲什麼hbase的數據是可靠的

    基於hdfs,由hdfs的可靠性保證了hbase的可靠性,即數據可以有多個備份。

    利用zookeeper實現了HA(高可用集羣),即使某一臺機器掛掉另外的機器也可以很快的替換它。

4.hbase和hive和傳統的關係型數據庫的比較

    比起傳統的關係型數據庫,可以存儲半結構化非結構化的數據,可以存儲和處理更大級別的數據,提供高效的查詢,對於稀疏數據的處理更好,具有更好的橫向擴展性,免費開源性價比很高。但是不能支持非常好的事務特性,只支持行級的事務。只能通過行鍵來查詢,表設計時難度更高。而mysql用來存儲結構化的數據提供更好的事務控制。

    比起hive,hive只是在mapreduce上包了一層殼,本質上還是離線數據的處理的工具,實時查詢性能有限,本質上是一個基於hadoop的數據倉庫工具,不能支持行級別的新增修改和刪除。hbase可以提供實時的數據的處理能力,適用於在線數據查詢處理,本質上是一種數據庫工具。

二、HBase的表設計

    HBase表的設計會直接影響hbase使用的效率和使用的便利性。

    HBase表的設計主要是列族的設計和行鍵的設計。

1、列族的設計

    在設計hbase表時候,注意以下事項:

    1.列族不宜過多,越少越好,官方推薦hbase表的列族不宜超過3個。列族設計過多,會非常消耗內存。

    2.經常要在一起查詢的數據最好放在一個列族中,儘量的減少跨列族的數據訪問。

    3.如果有多個列族,多個列族中的數據應該設計的比較均勻。

2、行鍵的設計

    hbase表中行鍵是唯一標識一個表中行的字段,所以行鍵設計的好不好將會直接影響未來對hbase的查詢的性能和查詢的便利性,所以hbase中的行鍵是需要進行設計的。

1.行鍵設計的基本原則

1>必須唯一

    行鍵必須唯一才能唯一標識數據。

2>必須有意義

    行鍵必須有意義,這樣才能方便數據的查詢。

3>最好是字符串類型

    所有語言平臺針對字符串的操作是統一,數值類型在不同的系統中處理的方式可能不同。

4>最好具有固定的長度

    不同長度的數據可能會造成自然排序時排序的結果和預期不一致。

5>不宜過長

    行鍵最多可以達到64KB,但是最好是在10~100字節之間,最好不要超過16字節,越短越好,最好是8字節的整數倍。

    底層存儲是利用key-value存儲的,行鍵會多次出現,如果行鍵過長會導致大量存儲空間被行鍵消耗掉。

2.行鍵的最佳實踐

    綜合來看以下兩個原則是存在衝突的,所以在選擇的時候只能使用其中之一,具體使用那個原則,要根據實際的業務以及集羣的能力來考慮。

1>散列原則

    行鍵的設計將會影響數據在hbase表中的排序方式,這會影響region切分後的結果,要注意,在設計行鍵時應該讓經常要查詢的數據分散在不同的region中,防止某一個或某幾個regionserver成爲熱點。

    當出現熱點數據的時候,會導致整個集羣的服務器相繼掛機,最終導致集羣崩潰,即雪崩。

2>有序原則

    行鍵的設計將會影響數據在hbase表中的排序方式,所以一種策略是將經常連續查詢的條件作爲行鍵最前面的數據,這樣一來可以方便批量查詢。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章