Hbase數據庫


 
 

1.簡介

HBase從誕生至今將近10年,在apache基金會的孵化下,已經變成一個非常成熟的項目,也有許多不同的公司支持着許多不同的分支版本,如cloudra等等。

HBase不同於一般的關系數據庫,它是一個適合於非結構化數據存儲的數據庫。另一個不同的是HBase基於列的而不是基於行的模式。

avatar

hadoop所有應用都是構建於hdfs(它提供高可靠的底層存儲支持,幾乎已經成為分布式文件存儲系統事實上的工業標准)之上的分布式列存儲系統,主要用於海量結構化數據存儲。通過Hadoop生態圈,可以看到HBase的身影,可見HBase在Hadoop的生態圈是扮演這一個重要的角色那就是 實時、分布式、高維數據 的數據存儲;

avatar

  • 特性:
    • 強一致性讀寫:HBase不是“Eventual Consistentcy(最終一致性)”數據存儲,這讓它很適合高速計數聚合類任務;
  • 自動分片(Automatic sharding):HBase表通過region分布在集群中,數據增長時,region會自動分割並重新分布;

  • RegionServer自動故障轉移

  • Hadoop/HDFS集成:HBase支持開箱即用HDFS作為它的分布式文件系統;

  • MapRecue:HBase通過MapRecue支持大並發處理;

  • Java客戶端API:HBase支持易於使用的Java API進行編程訪問;

  • Thrift/REST API:HBase也支持Thrift和Rest作為非Java前端訪問;

  • Block Cache和Bloom Filter:對於大容量查詢優化,HBase支持Block Cache和Bloom Filter;

  • 運維管理:HBase支持JMX提供內置網頁用於運維。

  • HBase的優點
    • 列可以動態增加,並且列為空就不存儲數據,節省存儲空間;
  • HBase可以自動切分數據,使得數據存儲自動具有水平擴展功能;

  • HBase可以提供高並發讀寫操作的支持;

  • 與Hadoop MapRecue相結合有利於數據分析;

  • 容錯性;版權免費;非常靈活的模式設計(或者說沒有固定模式的限制);

  • 可以跟Hive集成,使用類SQL查詢;

  • 自動故障轉移;客戶端接口易於使用;

  • 行級別原子性,即PUT操作一定是完全成功或者完全失敗。

  • HBase的缺點
    • HDFS是分布式文件系統,適合保存大文件。官方宣稱它並非普通用途的文件系統,不提供文件的個別記錄的快速查詢。
  • 另一方面,HBase基於HDFS,並能夠提供大表的記錄快速查詢和更新。HBase內部將數據放到索引好的“StoreFiles”存儲文件中,以便提供高速查詢,而存儲文件位於HDFS中。

 

2.典型應用

  1. FacebookFacebook用HBase存儲在線消息,每天數據量近百億,每月數據量250 ~ 300T, HBase讀寫比基本在1:1,吞吐量150w qps

  2. 小米10+在線HBase集群,好幾百台服務器,米聊歷史數據,消息push系統等多個重要應用系統都建立在HBase基礎之上網易哨兵監控系統,雲信歷史數據,日志歸檔數據等一系列重要應用底層都由HBase提供服務。

  3. 網易哨兵監控系統,雲信歷史數據,日志歸檔數據等一系列重要應用底層都由HBase提供服務。


 

3.適用場景

  1. 寫密集型應用,每天寫入量巨大,而相對讀數量較小的應用,比如IM的歷史消息,游戲的日志等等

  2. 不需要復雜查詢條件來查詢數據的應用,HBase只支持基於rowkey的查詢,對於HBase來說,單條記錄或者小范圍的查詢是可以接受的,大范圍的查詢由於分布式的原因,可能在性能上有點影響,而對於像SQL的join等查詢,HBase無法支持。

  3. 對性能和可靠性要求非常高的應用,由於HBase本身沒有單點故障,可用性非常高。 數據量較大,而且增長量無法預估的應用,HBase支持在線擴展,即使在一段時間內數據量呈井噴式增長,也可以通過HBase橫向擴展來滿足功能。

    • HBase作為默認的大數據時代的存儲,基本解決以下三大類的場景:
  1. 平台類:存放是平台的產品,就是其它軟件的存儲,比如目前很就行的Kylin,阿里內部的日志同步工具TT,圖組件Titan等。此類存放的往往平台的數據,有時候往往是無業務含義的。作為平台的底層存儲使用。

  2. 用戶行為類:此類主要是面向各個業務系統。這里的用戶不僅僅指的人,也包括物,比如物聯網。在阿里主要還是人產生的數據,比如:淘寶收藏夾、交易數據、旺旺聊天記錄等等。這里使用比較直接,就直接存放HBase,再讀取。難度就是需要支持千萬級別的並發寫訪問及讀取,需要解決服務質量的問題。

  3. 報表類的需求:比如報表、大屏等,如阿里巴巴的天貓雙十一大屏。


 

4.Habse數據結構

HBase不是一個關系型數據庫,它需要不同的方法定義你的數據模型,HBase實際上定義了一個四維數據模型,下面就是每一維度的定義:

  • 行鍵:每行都有唯一的行鍵,行鍵沒有數據類型,它內部被認為是一個字節數組。

    • 決定一行數據的唯一標識
    • RowKey是按照字典順序排序的。
    • Row key最多只能存儲64k的字節數據。
  • 列簇:數據在行中被組織成列簇,每行有相同的列簇,但是在行之間,相同的列簇不需要有相同的列修飾符。在引擎中,HBase將列簇存儲在它自己的數據文件中,所以,它們需要事先被定義,此外,改變列簇並不容易。

  • 列修飾符:列簇定義真實的列,被稱之為列修飾符,你可以認為列修飾符就是列本身。

     

    • Cell單元格:

       

      • 由行和列的坐標交叉決定;
      • 單元格是有版本的(由時間戳來作為版本);
      • 單元格的內容是未解析的字節數組(Byte[]),cell中的數據是沒有類型的,全部是字節碼形式存貯。
      • 由{row key,column(= +),version}唯一確定的單元。
  • 版本:每列都可以有一個可配置的版本數量,你可以通過列修飾符的制定版本獲取數據。

     

    • Timestamp時間戳:

       

      在HBase每個cell存儲單元對同一份數據有多個版本,根據唯一的時間戳來區分每個版本之間的差異,不同版本的數據按照時間倒序排序,最新的數據版本排在最前面。

      • 時間戳的類型是64位整型。
      • 時間戳可以由HBase(在數據寫入時自動)賦值,此時時間戳是精確到毫 秒的當前系統時間。
      • 時間戳也可以由客戶顯式賦值,如果應用程序要避免數據版本沖突, 就必須自己生成具有唯一性的時間戳。

avatar

如圖1中所示,通過行鍵獲取一個指定的行,它由一個或多個列簇構成,每個列簇有一個或多個列修飾符(圖1中稱為列),每列又可以有一個或多個版本。為了獲取指定數據,你需要知道它的行鍵、列簇、列修飾符以及版本。當設計HBase數據模型時,對考慮數據是如何被獲取是十分有幫助的。你可以通過以下兩種方式獲得HBase數據:
* 通過他們的行鍵,或者一系列行鍵的表掃描。

  • 使用map-reduce進行批操作

 

5.Habse數據結表設計

key是我們所提到過的行鍵,value是列簇的集合。你可以通過key檢索到value,或者換句話說,你可以通過行鍵“得到”行,或者你能通過給定起始和終止行鍵檢索一系列行,這就是前面提到的表掃描。你不能實時的查詢一個列的值,這就引出了一個重要的話題:行鍵的設計。

  • 有兩個原因令行鍵的設計十分重要:
  1. 表掃描是對行鍵的操作,所以,行鍵的設計控制着你能夠通過HBase執行的實時/直接獲取量。
  2. 當在生產環境中運行HBase時,它在HDFS上部運行,數據基於行鍵通過HDFS,如果你所有的行鍵都是以user-開頭,那么很有可能你大部分數據都被分配一個節點上(違背了分布式數據的初衷),因此,你的行鍵應該是有足夠的差異性以便分布式地通過整個部署。

 

6.Hbase優化

  1. 預先分區

默認情況下,在創建 HBase 表的時候會自動創建一個 Region 分區,當導入數據的時候,所有的 HBase 客戶端都向這一個 Region 寫數據,直到這個 Region 足夠大了才進行切分。一種可以加快批量寫入速度的方法是通過預先創建一些空的 Regions,這樣當數據寫入 HBase 時,會按照 Region 分區情況,在集群內做數據的負載均衡。

  1. Rowkey優化

HBase 中 Rowkey 是按照字典序存儲,因此,設計 Rowkey 時,要充分利用排序特點,將經常一起讀取的數據存儲到一塊,將最近可能會被訪問的數據放在一塊。

此外,Rowkey 若是遞增的生成,建議不要使用正序直接寫入 Rowkey,而是采用 reverse 的方式反轉Rowkey,使得 Rowkey 大致均衡分布,這樣設計有個好處是能將 RegionServer 的負載均衡,否則容易產生所有新數據都在一個 RegionServer 上堆積的現象,這一點還可以結合 table 的預切分一起設計。

  1. 減少列族數量

不要在一張表里定義太多的 ColumnFamily。目前 Hbase 並不能很好的處理超過 2~3 個 ColumnFamily 的表。因為某個 ColumnFamily 在 flush 的時候,它鄰近的 ColumnFamily 也會因關聯效應被觸發 flush,最終導致系統產生更多的 I/O。

  1. 緩存策略

創建表的時候,可以通過 HColumnDescriptor.setInMemory(true) 將表放到 RegionServer 的緩存中,保證在讀取的時候被 cache 命中。

  1. 設置存儲生命期

創建表的時候,可以通過 HColumnDescriptor.setTimeToLive(int timeToLive) 設置表中數據的存儲生命期,過期數據將自動被刪除。

  1. 硬盤配置

每台 RegionServer 管理 10~1000 個 Regions,每個 Region 在 1~2G,則每台 Server 最少要 10G,最大要1000*2G=2TB,考慮 3 備份,則要 6TB。方案一是用 3 塊 2TB 硬盤,二是用 12 塊 500G 硬盤,帶寬足夠時,后者能提供更大的吞吐率,更細粒度的冗余備份,更快速的單盤故障恢復。

  1. 分配合適的內存給RegionServer服務

在不影響其他服務的情況下,越大越好。例如在 HBase 的 conf 目錄下的 hbase-env.sh 的最后添加 export HBASE_REGIONSERVER_OPTS="-Xmx16000m$HBASE_REGIONSERVER_OPTS”
其中 16000m 為分配給 RegionServer 的內存大小。

  1. 寫數據的備份數

備份數與讀性能成正比,與寫性能成反比,且備份數影響高可用性。有兩種配置方式,一種是將 hdfs-site.xml拷貝到 hbase 的 conf 目錄下,然后在其中添加或修改配置項 dfs.replication 的值為要設置的備份數,這種修改對所有的 HBase 用戶表都生效,另外一種方式,是改寫 HBase 代碼,讓 HBase 支持針對列族設置備份數,在創建表時,設置列族備份數,默認為 3,此種備份數只對設置的列族生效。

  1. WAL(預寫日志)

可設置開關,表示 HBase 在寫數據前用不用先寫日志,默認是打開,關掉會提高性能,但是如果系統出現故障(負責插入的 RegionServer 掛掉),數據可能會丟失。配置 WAL 在調用 JavaAPI 寫入時,設置 Put 實例的WAL,調用 Put.setWriteToWAL(boolean)。

  1. 批量寫

HBase 的 Put 支持單條插入,也支持批量插入,一般來說批量寫更快,節省來回的網絡開銷。在客戶端調用JavaAPI 時,先將批量的 Put 放入一個 Put 列表,然后調用 HTable 的 Put(Put 列表) 函數來批量寫。

  1. 客戶端一次從服務器拉取的數量

通過配置一次拉去的較大的數據量可以減少客戶端獲取數據的時間,但是它會占用客戶端內存。有三個地方可進行配置:

  1. 在 HBase 的 conf 配置文件中進行配置 hbase.client.scanner.caching;

  2. 通過調用HTable.setScannerCaching(intscannerCaching) 進行配置;

  3. 通過調用Scan.setCaching(intcaching) 進行配置。三者的優先級越來越高。

  1. RegionServer的請求處理I/O線程數

較少的 IO 線程適用於處理單次請求內存消耗較高的 Big Put 場景 (大容量單次 Put 或設置了較大 cache 的Scan,均屬於 Big Put) 或 ReigonServer 的內存比較緊張的場景。

較多的 IO 線程,適用於單次請求內存消耗低,TPS 要求 (每秒事務處理量 (TransactionPerSecond)) 非常高的場景。設置該值的時候,以監控內存為主要參考。

在 hbase-site.xml 配置文件中配置項為 hbase.regionserver.handler.count。

  1. Region的大小設置

配置項為 hbase.hregion.max.filesize,所屬配置文件為 hbase-site.xml.,默認大小 256M。

在當前 ReigonServer 上單個 Reigon 的最大存儲空間,單個 Region 超過該值時,這個 Region 會被自動 split成更小的 Region。小 Region 對 split 和 compaction 友好,因為拆分 Region 或 compact 小 Region 里的StoreFile 速度很快,內存占用低。缺點是 split 和 compaction 會很頻繁,特別是數量較多的小 Region 不停地split, compaction,會導致集群響應時間波動很大,Region 數量太多不僅給管理上帶來麻煩,甚至會引發一些Hbase 的 bug。一般 512M 以下的都算小 Region。大 Region 則不太適合經常 split 和 compaction,因為做一次 compact 和 split 會產生較長時間的停頓,對應用的讀寫性能沖擊非常大。

此外,大 Region 意味着較大的 StoreFile,compaction 時對內存也是一個挑戰。如果你的應用場景中,某個時間點的訪問量較低,那么在此時做 compact 和 split,既能順利完成 split 和 compaction,又能保證絕大多數時間平穩的讀寫性能。compaction 是無法避免的,split 可以從自動調整為手動。只要通過將這個參數值調大到某個很難達到的值,比如 100G,就可以間接禁用自動 split(RegionServer 不會對未到達 100G 的 Region 做split)。再配合 RegionSplitter 這個工具,在需要 split 時,手動 split。手動 split 在靈活性和穩定性上比起自動split 要高很多,而且管理成本增加不多,比較推薦 online 實時系統使用。內存方面,小 Region 在設置memstore 的大小值上比較靈活,大 Region 則過大過小都不行,過大會導致 flush 時 app 的 IO wait 增高,過小則因 StoreFile 過多影響讀性能。

  1. 操作系統參數

Linux系統最大可打開文件數一般默認的參數值是1024,如果你不進行修改並發量上來的時候會出現“Too Many Open Files”的錯誤,導致整個HBase不可運行,你可以用ulimit -n 命令進行修改,或者修改/etc/security/limits.conf和/proc/sys/fs/file-max 的參數,具體如何修改可以去Google 關鍵字 “linux limits.conf ”

  1. Jvm配置

修改 hbase-env.sh 文件中的配置參數,根據你的機器硬件和當前操作系統的JVM(32/64位)配置適當的參數

HBASE_HEAPSIZE 4000 HBase使用的 JVM 堆的大小

HBASE_OPTS "‐server ‐XX:+UseConcMarkSweepGC"JVM GC 選項

HBASE_MANAGES_ZKfalse 是否使用Zookeeper進行分布式管理

  1. 持久化

重啟操作系統后HBase中數據全無,你可以不做任何修改的情況下,創建一張表,寫一條數據進行,然后將機器重啟,重啟后你再進入HBase的shell中使用 list 命令查看當前所存在的表,一個都沒有了。是不是很杯具?沒有關系你可以在hbase/conf/hbase-default.xml中設置hbase.rootdir的值,來設置文件的保存位置指定一個文件夾,例如:file:///you/hbase-data/path,你建立的HBase中的表和數據就直接寫到了你的磁盤上,同樣你也可以指定你的分布式文件系統HDFS的路徑例如:hdfs://NAMENODE_SERVER:PORT/HBASE_ROOTDIR,這樣就寫到了你的分布式文件系統上了。

  1. 緩沖區大小

hbase.client.write.buffer

這個參數可以設置寫入數據緩沖區的大小,當客戶端和服務器端傳輸數據,服務器為了提高系統運行性能開辟一個寫的緩沖區來處理它,這個參數設置如果設置的大了,將會對系統的內存有一定的要求,直接影響系統的性能。

  1. 掃描目錄表

hbase.master.meta.thread.rescanfrequency

定義多長時間HMaster對系統表 root 和 meta 掃描一次,這個參數可以設置的長一些,降低系統的能耗。

  1. split/compaction時間間隔

hbase.regionserver.thread.splitcompactcheckfrequency

這個參數是表示多久去RegionServer服務器運行一次split/compaction的時間間隔,當然split之前會先進行一個compact操作.這個compact操作可能是minorcompact也可能是major compact.compact后,會從所有的Store下的所有StoreFile文件最大的那個取midkey.這個midkey可能並不處於全部數據的mid中.一個row-key的下面的數據可能會跨不同的HRegion。

  1. 緩存在JVM堆中分配的百分比

hfile.block.cache.size

指定HFile/StoreFile 緩存在JVM堆中分配的百分比,默認值是0.2,意思就是20%,而如果你設置成0,就表示對該選項屏蔽。

  1. ZooKeeper客戶端同時訪問的並發連接數

hbase.zookeeper.property.maxClientCnxns

這項配置的選項就是從zookeeper中來的,表示ZooKeeper客戶端同時訪問的並發連接數,ZooKeeper對於HBase來說就是一個入口這個參數的值可以適當放大些。

  1. memstores占用堆的大小參數配置

hbase.regionserver.global.memstore.upperLimit

在RegionServer中所有memstores占用堆的大小參數配置,默認值是0.4,表示40%,如果設置為0,就是對選項進行屏蔽。

  1. Memstore中緩存寫入大小

hbase.hregion.memstore.flush.size

Memstore中緩存的內容超過配置的范圍后將會寫到磁盤上,例如:刪除操作是先寫入MemStore里做個標記,指示那個value, column 或 family等下是要刪除的,HBase會定期對存儲文件做一個major compaction,在那時HBase會把MemStore刷入一個新的HFile存儲文件中。如果在一定時間范圍內沒有做major compaction,而Memstore中超出的范圍就寫入磁盤上了。


免責聲明!

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



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