HBase 預分區 & Phoenix 加鹽


HBase 熱點問題

剛創建 HBase 表的時候默認只有一個 Region 由一個 Region Server 管理,在數據量達到一定值的時候會觸發分裂 split,這樣會不斷的分裂出更多的 Region,由不同的 Region Server 管理,每個 Region 管理的是一段連續的 row key,由 start row key 和 end row key 表示,這樣會出現兩個問題

  1. 無法充分利用分布式並發處理的優勢,必須等待 Region 自動分裂成多個,這個過程可能會很久
  2. 由於每個 Region 管理一段連續的 row key,這樣如果數據的讀寫不夠隨機,比如有自增 ID,比如大量操作集中在某段 row key,這樣有可能導致壓力都在同一個 Region 上

Region 分裂策略

定義在 hbase-site.xml 文件

<name>hbase.regionserver.region.split.policy</name>
<value>org.apache.hadoop.hbase.regionserver.IncreasingToUpperBoundRegionSplitPolicy</value>
<description>
  A split policy determines when a region should be split. The various other split policies that
  are available currently are ConstantSizeRegionSplitPolicy, DisabledRegionSplitPolicy,
  DelimitedKeyPrefixRegionSplitPolicy, KeyPrefixRegionSplitPolicy etc.
</description>

默認策略是 IncreasingToUpperBoundRegionSplitPolicy,在 HBase 1.2 中,這個策略默認表示,當 Region 的大小達到 Region 個數的立方乘以 hbase.hregion.memstore.flush.size(默認 128 MB)再乘以 2 ,或是達到 hbase.hregion.max.filesize (默認 10 GB)時,就對該 Region 做分裂操作

第一次分裂的大小:1^3 * 128MB * 2 = 256MB
第二次分裂的大小:2^3 * 128MB * 2 = 2048MB
第三次分裂的大小:3^3 * 128MB * 2 = 6912MB
第四次分裂的大小:4^3 * 128MB * 2 = 16384MB,超過了 10GB,因此只取 10GB
后面的分裂大小都是 10GB

可以看到如果可以利用的節點比較多的話,那么可能得等很久才能充分利用

預分區

第一種預分區的方法

hbase org.apache.hadoop.hbase.util.RegionSplitter tablename HexStringSplit -c 10 -f f1:f2:f3

上面的命令表示創建一張名為 tablename 的表,這張表預先分配了 10 個 Region,有三個 CF,分別是 f1、f2、f3,預分區算法是 HexStringSplit,也可以選擇 UniformSplit,其中 HexStringSplit 適合 row key 的前綴是十六進制的字符串的,UniformSplit 適合 row key 前綴完全隨機的,預分區后,哪怕連續的 row key, HBase 也會通過算法將其分到不同的 Region,實現均勻分布,避免熱點


第二種預分區的方法

hbase shell > create 'tablename', 'f1', SPLITS=> ['10', '20', '30', '40']

當可以提前知道 row key 的分布的時候,可以指定每個預分區的 region 的分割點,上面命令創建的表中,有 5 個 Region

Region 1 : row key 的前兩位是 min~10
Region 2 : row key 的前兩位是 10~20
Region 3 : row key 的前兩位是 20~30
Region 4 : row key 的前兩位是 30~40
Region 5 : row key 的前兩位是 40~max

注意這里不單指數字字符,比如 1a 就會落在 Region 2


對已存在的表可以做強制分裂

hbase shell > split 'table', 'split point'


此外也可以設計自己的分裂方法

Phoenix 加鹽

CREATE TABLE IF NOT EXISTS Product (
    id           VARCHAR not null,
    time         VARCHAR not null,
    price        FLOAT,
    sale         INTEGER,
    inventory    INTEGER,

    CONSTRAINT pk PRIMARY KEY (id, time)
) COMPRESSION = 'GZ', SALT_BUCKETS = 6

本質上是對 HBase 表的 row key 做了哈希后,對 SALT_BUCKETS 取余數,並將結果(上面的例子中是 0~5)作為 byte 插入到 row key 的第一位,根據這個數值將數據分到不同 Region 中,由於是作為 byte 存儲,所以 SALT_BUCKETS 能取的最大值是 256,擁有相同 salt byte 的 row 會被分到相同的 region server,所以通常取 region server 的數量作為 SALT_BUCKETS


由於加了鹽的數據最前面多了一位,這樣默認情況下,從不同 region server 取出來的數據無法按原來的 row key 排序,如果需要保證排序,需要改一個配置

phoenix.query.force.rowkeyorder = true



免責聲明!

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



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