HBASE基本概念以及使用場景

備註:本文原爲項目內分享(2017-12-18),部分內容來自於網絡,多有借鑑之處

前言:

古人有言,欲修仙者,財侶法地缺一不可。

所謂侶,即同修、道友。
  修仙漫漫不歸路,多少人在攀登高峯的時候,或失足,或飢寒,或懈怠,倒在路邊。這個時候,假如有人扶你一把,給你半個饅頭,也許你就有了前進的動力,這就是道侶。

    簡而言之,共同學習,共同探討,共同進步的同志。

科普中國-百科科學詞條

      HBase是一個分佈式的、面向列的開源數據庫,該技術來源於 Fay Chang 所撰寫的Google論文“Bigtable:一個結構化數據的分佈式存儲系統”。就像Bigtable利用了Google文件系統(File System)所提供的分佈式數據存儲一樣,HBase在Hadoop之上提供了類似於Bigtable的能力。HBase是Apache的Hadoop項目的子項目。HBase不同於一般的關係數據庫,它是一個適合於非結構化數據存儲的數據庫。另一個不同的是HBase基於列的而不是基於行的模式。






列簇維度、時間維度(默認3個)在 Hbase 中,Row-key 加上 CF(列簇) 加上 Qulifier(列) 再加上一個時間戳纔可以定位到一個單元格數據(Hbase 中每個單元格默認有 3 個時間戳的版本數據)查詢命令:get 'ns_scpdm:tdm_fillup_suggest_order_d','003173091_7616_04_20171110_10127836_00360374250501' 



從技術上來說,Hbase 更像是"數據存儲"而非"數據庫"

     因此,HBase 缺少很多 RDBMS 特性,如列類型,二級索引,觸發器和高級查詢語言等。然而, HBase 也具有許多其他特徵同時支持線性化和模塊化擴充。最明顯的方式,我們可以通過增加 Region Server 的數量擴展 HBase。並且 HBase 可以放在普通的服務器中,例如將集羣從 5 個擴充到 10 個 Region Server 時,存儲空間和處理容量都可以同時翻倍。當然 RDBMS 也能很好的擴充,但僅對一個點,尤其是對一個單獨數據庫服務器而言,爲了更好的性能,往往需要特殊的硬件和存儲設備(往往價格也非常昂貴)。


HBase 的工作流程

    無需過多瞭解
只是關注如何使用以及使用場景

首先,要確信有足夠多數據,如果有上億或上千億行數據,HBase 纔會是一個很好的備選。其次,需要確信業務上可以不依賴 RDBMS 的額外特性,例如,列數據類型, 二級索引,SQL 查詢語言等。再而,需要確保有足夠硬件。且不說 HBase,一般情況下當 HDFS 的集羣小於 5 個數據節點時,也幹不好什麼事情 (HDFS 默認會將每一個 Block 數據備份 3 分),還要加上一個 NameNode。


其實rowkey設計準則一般就2條

     1、唯一性


   2、散列性(數據傾斜--熱點)
   商品編碼一般是反轉就能散列,但是 如果有的商品編碼就1條記錄,有的商品編碼有幾百萬條記錄 那麼這樣數據還是傾斜掉   了。

   蛋疼,這個 就涉及到了HBASE的工作流程


爲啥有那倆個設計原則呢?

     首先,一個 HBase 數據庫是否高效,很大程度會和 Row-Key 的設計有關。因此,如何設計 Row-key 是使用 HBase 時,一個非常重要的話題。隨着數據訪問方式的不同,Row-Key 的設計也會有所不同。不過概括起來的宗旨只有一個,那就是儘可能選擇一個 Row-Key,可以使你的數據均勻的分佈在集羣中。這也很容易理解,因爲 HBase 是一個分佈式環境,Client 會訪問不同 Region Server 獲取數據。如果數據排布均勻在不同的多個節點,那麼在批量的 Client 便可以從不同的 Region Server 上獲取數據,而不是瓶頸在某一個節點,性能自然會有所提升。對於具體的建議我們一般有幾條:

     一切都是爲了搞笑-高效:

當客戶端需要頻繁的寫一張表,隨機的 RowKey 會獲得更好的性能。
當客戶端需要頻繁的讀一張表,有序的 RowKey 則會獲得更好的性能。

對於時間連續的數據(例如 log),有序的 RowKey 會很方便查詢一段時間的數據(Scan 操作)。例如:key:20171201,20171202

場景、功能描述:

  數據庫(包括其他一些關係型數據庫)在單表記錄數超過100w時就會變得很慢。解決方法是分表,或者遷移到專注於處理海量數據的NoSQL
a)HBase對數據操作的響應速度與當前表中的數據量無關,但是與數據的split以及本地緩存等配置項有很大關係。 比如rowKey的合理設計,使相關數據相鄰存放;比如使用scan時setCatch(num)方法中num的取值。

b)HBase對數據操作的響應在毫秒級,滿足我們前端顯示的需要


HBase獲得記錄總數很困難,瀏覽所有數據倒好說,我可以在數據庫中存一下當前數據庫中記錄的總數。如果滿足條件的記錄有1億條,我總不能先遍歷一邊記個數啊……
聽說在MapReduce層可以有辦法完成總數的統計
因此分頁比較坑
因此hbase就不適合分頁,但總是有取巧的法子及其對應的應用場景
1、scan全查出來,自己手寫分頁
2、不計算總頁數,利用pagefilter,startKey只保證上一頁,下一頁


案例:

      1、精確查詢
         數據量:2億條數據   平均日銷:get     0.3秒
     rowkey:CommonUtil.convertStr(cmmdtyCode)+"_" + supplyPlant+"_" + plantType +"_"+lastDate
  2、模糊查詢
                 OMS訂單:scan
     rowkey:CommonUtil.convertStr(cmmdtyCode)+"_" + supplyPlant+"_" + plantType +"_"+lastDate+”_”+訂單號,
     前綴一致,獲得多條記錄
    3、分頁查詢pagefilter  :分頁效率比較低,應爲每次都需要掃描前面的數據,直到掃描到所需要查的數據,但是查詢下一頁的時候可以直接利用上一頁的rowkey來直接查出,查詢總數效率特低,不建議使用。

             用過濾器的前提是:   你scan的數據範圍 已經用 start 和end 限定的很小了,基於列的過濾都是沒有索引的 性能很差   


結構圖:

          

數據傾斜:

Hbase的表會被劃分爲1....n個Region,被託管在RegionServer中。Region二個重要的屬性:Startkey與EndKey表示這個Region維護的rowkey的範圍,當我們要讀寫數據時,如果rowkey落在某個start-end key範圍內,那麼就會定位到目標region並且讀寫到相關的數據。
    默認情況下,當我們通過hbaseAdmin指定TableDescriptor來創建一張表時,只有一個region正處於混沌時期,start-end key無邊界,可謂海納百川。所有的rowkey都寫入到這個region裏,然後數據越來越多,region的size越來越大時,大到一定的閥值,hbase就會將region一分爲二,成爲2個region,這個過程稱爲分裂(region-split)。
    如果我們就這樣默認建表,表裏不斷的put數據,更嚴重的是我們的rowkey還是順序增大的,是比較可怕的。存在的缺點比較明顯:首先是熱點寫,我們總是向最大的start key所在的region寫數據,因爲我們的rowkey總是會比之前的大,並且hbase的是按升序方式排序的。所以寫操作總是被定位到無上界的那個region中;其次,由於熱點,我們總是往最大的start key的region寫記錄,之前分裂出來的region不會被寫數據,有點打入冷宮的感覺,他們都處於半滿狀態,這樣的分佈也是不利的。
    如果在寫比較頻繁的場景下,數據增長太快,split的次數也會增多,由於split是比較耗費資源的,所以我們並不希望這種事情經常發生。
    在集羣中爲了得到更好的並行性,我們希望有好的load blance,讓每個節點提供的請求都是均衡的,我們也不希望,region不要經常split,因爲split會使server有一段時間的停頓,如何能做到呢?

    隨機散列與預分區二者結合起來,是比較完美的。預分區一開始就預建好了一部分region,這些region都維護着自己的start-end keys,在配合上隨機散列,寫數據能均衡的命中這些預建的region,就能解決上面的那些缺點,大大提供性能。


解決思路-額外:

       提供兩種思路:hash與partition




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