天天看點

HBase 列族屬性配置

一、建立表及屬性檢視

建立一個測試表 test,列族為 cf:

create 'test', {NAME => 'cf'}
           

預設屬性如下:

hbase > describe 'test'

{
NAME => 'cf', 
BLOOMFILTER => 'ROW', 
VERSIONS => '1', 
IN_MEMORY => 'false', 
KEEP_DELETED_CELLS => 'FALSE', 
DATA_BLOCK_ENCODING => 'NONE', 
TTL => 'FOREVER', 
COMPRESSION => 'GZ', 
MIN_VERSIONS => '0', 
BLOCKCACHE => 'true',
BLOCKSIZE => '65536', 
REPLICATION_SCOPE => '0'
}   
           

二、列族屬性配置

HBase 列族屬性配置

2.1、版本數量(VERSIONS)

HBase 一切操作均為更新,Hbase Put 操作不會去覆寫一個值,隻會在後面追加寫,用時間戳(版本号)來區分,HBase 版本次元按遞減順序存儲,以便在從存儲檔案讀取時,首先找到最近的值;Hbase Delete 操作也不是真正删除了記錄,而是放置了一個墓碑标記,過早的版本會在執行 Major Compaction 時真正删除。

0.96版本預設是3個, 0.98版本之後是1, 要根據業務來劃分,版本是曆史記錄,版本增多意味空間消耗。

插入資料的時候,版本預設是目前時間;查詢的時候可以指定要擷取的版本個數

get 'test', { COLUMN => 'cf', VERSIONS => 2}

擷取多個版本的時候,多個資料是按照時間戳倒序排序,也可以通過這個特性,來儲存類似于事件發生的資料,查詢時間曆史的時候,拿出來的資料是按照時間排好序,如果要拿最新的事件,不指定版本即可。

版本的時間戳,也可以自定義,不使用預設生成的時間戳,可以自己指定業務相關的ID。

使用方法:

create 'test1', {NAME => 'cf', VERSIONS => 3}
           

更改版本号:

alter 'test1', NAME => 'cf', VERSIONS => 5
           

2.2、存活時間(TTL)

TTL 全稱是 Time To Live,ColumnFamilies 可以設定 TTL(機關是s),HBase 會自動檢查 TTL 值是否達到上限,如果 TTL 達到上限後自動删除行。當然真正删除是在Major Compaction過程中執行的。

試驗一下:

alter 'test1', NAME => 'cf', VERSIONS => 5, TTL => 10

put 'test1', '0001', 'cf:name', 'james'

get 'test1', '0001'
           

發現過 10s 後資料已經删除。

2.3、最小版本數(MIN_VERSIONS )

如果 HBase 中的表設定了 TTL 的時候,MIN_VERSIONS 才會起作用。

每個列族可以設定最小版本數,最小版本數預設值是0,表示禁用該特性。最小版本數參數和存活時間是一起使用的,允許配置“如儲存最後T秒有價值的資料,最多N個版本,但最少M個版本”(M是最小版本,M<N)。

  • MIN_VERSION > 0時:Cell 至少有 MIN_VERSION 個最新版本會保留下來;
  • MIN_VERSION = 0時:Cell 中的資料超過TTL時間時,全部清空,不保留最低版本。

2.4、保留删除的單元格(KEEP_DELETED_CELLS)

HBase 的

delete

指令,并不是真的删除資料,而是設定一個标記(

delete marker

)。使用者在檢索資料的時候,會過濾掉這些标示的資料。

該屬性可以設定為

FALSE

(預設)、

TRUE

TTL

可以從 java API 源碼中看到:

public enum KeepDeletedCells {
  /** Deleted Cells are not retained. */
  FALSE,
  /**
   * Deleted Cells are retained until they are removed by other means
   * such TTL or VERSIONS.
   * If no TTL is specified or no new versions of delete cells are
   * written, they are retained forever.
   */
  TRUE,
  /**
   * Deleted Cells are retained until the delete marker expires due to TTL.
   * This is useful when TTL is combined with MIN_VERSIONS and one
   * wants to keep a minimum number of versions around but at the same
   * time remove deleted cells after the TTL.
   */
  TTL;
  public static KeepDeletedCells getValue(String val) {
    return valueOf(val.toUpperCase());
  }
}
           
  • FALSE:不保留删除的單元格。
  • TRUE:删除的單元格會保留,超期(TTL)或者資料版本數超過 VERSIONS 設定的值才會被删除;如果沒有指定 TTL 或沒有超出VERSIONS 值,則會永久保留它們。
  • TTL:超期(TTL)才會删除,當 TTL 與 MIN_VERSIONS 結合使用時,會删除過期後的資料,但是同時會保留最少數量的版本。

2.5、資料塊大小(BLOCKSIZE )

HBase 預設的塊大小是 64kb,不同于 HDFS 預設 64MB 的塊大小。

資料塊索引存儲每個 HFile 資料塊的起始鍵,資料塊大小配置會影響資料塊索引的大小。資料塊越小,資料塊索引越大,因而占用的記憶體空間越大。

同時,加載進記憶體的資料塊更小,随機查找性能更好,因為一旦找到了行鍵所在的塊,接下來就會定位對應的單元格,使用更小的資料塊效率更優。

但是如果需要更好的順序掃描性能,那麼一次能夠加載更多 HFile 資料進入記憶體則更為合理,這意味資料塊大小應該設定更大的值。相應索引将變小,将在随機讀性能上付出代價。

對于不同的業務資料,塊大小的合理設定對讀寫性能有很大的影響。如果業務請求以 Get 請求為主,可以考慮将塊大小設定較小;如果以 Scan 請求為主,可以将塊大小調大;預設的 64K 塊大小是在 Scan 和 Get 之間取得的一個平衡。

預設塊大小适用于多種資料使用模式,調整塊大小是比較進階的操作。配置錯誤将對性能産生負面影響。是以建議在調整之後進行測試,根據測試結果決定是否可以線上使用。

2.6、塊緩存(BLOCKCACHE)

預設是 true。緩存是記憶體存儲,HBase 使用塊緩存将最近使用的塊加載到記憶體中。塊緩存會根據最近最久未使用(LRU)的規則删除資料塊。

如果使用場景是經常順序通路 Scan 或者很少被通路,可以關閉列族的緩存。列族緩存預設是打開的。

2.7、激進緩存(IN_MEMORY)

HBase 可以選擇一個列族賦予更高的優先級緩存,激進緩存(表示優先級更高),

IN_MEMORY

預設是false。

如果設定為true,HBase 會嘗試将整個列族儲存在記憶體中,隻有在需要儲存是才會持久化寫入磁盤。但是在運作時 HBase 會嘗試将整張表加載到記憶體裡。

這個參數通常适合較小的列族。

2.8、壓縮(COMPRESSION)

資料壓縮是 HBase 提供的一個特性,HBase 在寫入資料塊到 HDFS 之前會首先對資料塊進行壓縮,再落盤,進而可以減少磁盤空間使用量。

而在讀資料的時候首先從 HDFS 中加載出 block 塊之後進行解壓縮,然後再緩存到BlockCache,最後傳回給使用者。

寫路徑和讀路徑分别如下:

  • 寫路徑: Finish DataBlock –> Encoding KVs –> Compress DataBlock –> Flush
  • 讀路徑: Read Block From Disk –> DeCompress DataBlock –> Cache DataBlock –> Decoding Scan KVs

壓縮可以節省空間,但讀寫資料會增加CPU負載,預設為 NONE,不使用用壓縮,HBase 目前提供了三種常用的壓縮方式: GZip, LZO, Snappy:

  1. GZIP 的壓縮率最高,但是 CPU 密集型的,對 CPU 的消耗比其他算法要多,壓縮和解壓速度也慢;
  2. LZO 的壓縮率居中,比 GZIP 要低一些,但是壓縮和解壓速度明顯要比GZIP 快很多,其中解壓速度快的更多;
  3. Snappy 的壓縮率最低,而壓縮和解壓速度要稍微比 LZO 要快一些。

綜合來看,Snappy 的壓縮率最低,但是編解碼速率最高,對 CPU 的消耗也最小,目前一般建議使用 Snappy。

2.9、布隆過濾器(BLOOMFILTER)

布隆過濾器用自己的算法,實作了快速的檢索一個元素是否在一個較大的元素清單之中。

它的基本思想是:當一個元素被加入集合時,通過 K 個散列函數将這個元素映射成一個位數組中的 K 個點,把它們置為1;檢索時,隻要看看這些點是不是都是1 就(大約)知道集合中有沒有它了——如果這些點有任何一個0,則被檢元素一定不在,如果都是1,則被檢元素很可能在。

它的優點是空間效率和查詢時間都遠遠超過一般的算法,缺點是有一定的誤識别率和删除困難使用了Hash算法,必然會存在極限巧合下的 hash 碰撞,會将不存在的資料認為是存在的。但是存在的資料一定是可以正确判斷的。

HBase 中的 BloomFilter 主要用來過濾不存在待檢索 RowKey 或者 Row-Col 的 HFile 檔案,避免無用的 IO 操作。它可以判斷 HFile 檔案中是否可能存在待檢索的KV,如果不存在,就可以不用消耗 IO 打開檔案進行 seek。通過設定 BloomFilter 可以提升随機讀寫的性能。

BloomFilter 是一個列族級别的配置屬性,如果在表中設定了BloomFilter,那麼HBase 會在生成 StoreFile 時包含一份 BloomFilter 結構的資料,稱其為

MetaBlock

,和

DataBlock

(真實KeyValue資料)一起由 LRUBlockCache 維護。是以開啟 BloomFilter 會有一定的存儲即記憶體 Cache 的開銷。

BloomFilter 取值有兩個,

row

rowcol

,需要根據業務來确定具體使用哪種。

  • 如果業務大多數随機查詢時僅僅使用 row 作為查詢條件,BloomFilter 設定為row;
  • 如果大多數随機查詢使用 row+cf 作為查詢條件,BloomFilter 需要設定為rowcol;
  • 如果不确定查詢類型,建議設定為 row。

2.10、資料塊編碼(DATA_BLOCK_ENCODING)

除了資料壓縮之外,HBase 還提供了資料編碼功能。

和壓縮一樣,資料在落盤之前首先會對 KV 資料進行編碼;但又和壓縮不同,資料塊在緩存前并沒有執行解碼。是以即使後續命中緩存的查詢是編碼的資料塊,需要解碼後才能擷取到具體的 KV 資料。

和不編碼情況相比,編碼後相同資料 block 塊占用記憶體更少,即記憶體使用率更高,但是讀取的時候需要解碼,又不利于讀性能,在記憶體不足的情況下,可以壓榨 CPU 字段,換區更多的緩存資料。

HBase目前提供了四種常用的編碼方式: Prefix_Tree、 Diff 、 Fast_Diff 、Prefix。

寫路徑和讀路徑分别如下:

  • 寫路徑: Finish DataBlock –> Encoding KVs –> Compress DataBlock –> Flush
  • 讀路徑: Read Block From Disk –> DeCompress DataBlock –> Cache DataBlock –> Decoding Scan KVs

2.11、複制範圍(REPLICATION_SCOPE )

HBase 提供了跨級群同步的功能,本地叢集的資料更新可以及時同步到其他叢集。複制範圍(replication scope)的參數預設為0,表示複制功能處于關閉狀态。

三、列族設定

3.1、列族數量

不要在一張表中定義太多的列族。

目前 HBase 并不能很好的處理 2~3 以上的列族,

flush

compaction

操作是針對一個 Region 的。

當一個列族操作大量資料的時候會引發一個 flush,它鄰近的列族也會因關聯效應被觸發 flush,盡管它沒有操作多少資料。compaction 操作是根據一個列族下的全部檔案的數量觸發的,而不是根據檔案大小觸發的。

當很多的列族在 flush 和 compaction 時,會造成很多沒用的 IO 負載。

盡量在模式中隻針對一個列族進行操作。将使用率相近的列歸為一個列族,這樣每次通路就隻用通路一個列族,既能提升查詢效率,也能保持盡可能少的通路不同的磁盤檔案。

3.2、列族的基數

如果一個表存在多個列族,要注意列族之間基數(如行數)相差不要太大。例如列族 A 有100 萬行,列族 B 有 10 億行,按照 RowKey 切分後,列族A可能被分散到很多很多 Region(及RegionServer),這導緻掃描列族A十分低效。

3.3、列族名、列名長度

列族名和列名越短越好,冗長的名字雖然可讀性好,但是更短的名字在 HBase 中更好。

一個具體的值由存儲該值的行鍵、對應的列(

列族:列

)以及該值的時間戳決定。HBase 中索引是為了加速随機通路的速度,索引的建立是基于“

行鍵+列族:列+時間戳+值

”的,如果行鍵和列族的大小過大,甚至超過值本身的大小,那麼将會增加索引的大小。并且在HBase中資料記錄往往非常之多,重複的行鍵、列将不但使索引的大小過大,也将加重系統的負擔。

四、總結

根據 HBase 列族屬性配置,結合使用場景,HBase 列族可以進行如下優化:

  1. 列族不宜過多,将相關性很強的 key-value 都放在同一個列族下;
  2. 盡量最小化行鍵和列族的大小;
  3. 提前預估資料量,再根據 RowKey 規則,提前規劃好 Region 分區,在建立表的時候進行預分區;
  4. 在業務上沒有特别要求的情況下,隻使用一個版本,即最大版本和最小版本一樣,均為1;
  5. 根據業務需求合理設定好失效時間(存儲的時間越短越好);
  6. 根據查詢條件,設定合理的BloomFilter配置。

文章來源:https://www.jianshu.com/p/5db1d7c557c7