hbase動態更改行鍵設計 HBase 行鍵設計

2021-10-17 06:41:34 字數 4114 閱讀 2650

hbase 有兩種基本的鍵結構:行鍵(row key)和列鍵(column key)。兩者都可以儲存有意義的資訊,一種是鍵本身儲存的內容,另一種是鍵的排列順序。

概念hbase 的表中資料分隔主要是使用列族(column family)而不是列,並非列式儲存,如下圖,表示了使用者邏輯上把乙個單元格的資料存到了一張表中,實際上底層儲存是按列族線性地儲存單元格,幷包含了一些必要資訊:

hbase

左上圖是資料的邏輯檢視,列鍵包含了列族和列(cf1:c1、cf2:c1...),每一行必須有乙個行鍵(r1、r2...),可以通過行鍵獲取到一行的所有列。

右上圖表示邏輯檢視轉換為實際物理儲存,每一行的每個單元格被有序儲存,不同列族的資料儲存在不同的檔案(store file)中,同乙個列族的資料儲存在乙個檔案中(實際上會有多個 hfile,邏輯上屬於同乙個)。並且單元格的每個歷史版本也會在儲存檔案中存在。

hbase 不儲存 null 值,所以表可以很稀疏,沒有值的單元格不會占用儲存空間。每個單元格在儲存檔案中都儲存了該記錄在表中所處位置的相關資訊。

如右下圖所示,每乙個單元格都包含:行鍵、列族、列鍵、寫入時間戳和列值。並且按照時間戳降序排列。在讀取 hfile 時最新的值會先被讀到。單元格在 hbase 中被叫做 keyvalue,儲存時先按行鍵排序,再按列鍵排序。因此使用者可以按行鍵、或按行鍵的範圍指定查詢,同時指定列族,可以有效的減少檢索的檔案。

列和時間戳也可以用來篩選資料。查詢資料時可以指定返回的列(可以配合過濾器 filter 實現比較複雜的篩選),也可以指定時間範圍進行過濾。

列值是最後乙個篩選條件,與列的篩選類似,對每乙個 keyvalue 都要經過過濾器檢查,對效能的提公升不明顯,會減少返回給客戶端的資料量。

下圖展示了使用不同欄位對篩選的效能影響大小。篩選的效率從左至右明顯下降,所以在 keyvalue 設計時,可以考慮把更重要的篩選資訊移動位置,如上圖左下圖展示的,在不改變資料量的情況下提高查詢效能。

hbase

高表與寬表

hbase 的表可以設計為高表(tall-narrow table)和寬表(flat-wide table)兩類。前者行多列少,後者行少列多。根據之前介紹的 keyvalue 的資訊篩選效率,應該盡量的將需要查詢的維度或資訊儲存在行鍵中,篩選的效率是最高的。

此外,hbase 按行進行資料分片,因此高表更有優勢。設想將使用者的所有電子郵件都儲存在一行,以使用者id作為行鍵,當郵件數量大時,極限場景下乙個使用者的資料超過了 hfile 的最大限制,而此次 hfile 是無法根據行鍵拆分的。(下面表示的是一行資料在物理儲存上的形式)

12345 : data : 5fc38314-e290-ae5da5fc375d : 1307097848 : "hi lars, ..."

12345 : data : 725aae5f-d72e-f90f3f070419 : 1307099848 : "welcome, and ..."

12345 : data : cc6775b3-f249-c6dd2b1a7467 : 1307101848 : "to whom it ..."

12345 : data : dcbee495-6d5e-6ed48124632c : 1307103848 : "hi, how are ..."

更好的方式轉換為高表,每個郵件一行,是行鍵以使用者id(userid)和訊息id(messageid)組合。訊息id在 keyvalue 中向左移動,不僅解決了 hfile 拆分的問題,同時提高了訊息id的檢索效率。

12345-5fc38314-e290-ae5da5fc375d : data : : 1307097848 : "hi lars, ..."

12345-725aae5f-d72e-f90f3f070419 : data : : 1307099848 : "welcome, and ..."

12345-cc6775b3-f249-c6dd2b1a7467 : data : : 1307101848 : "to whom it ..."

12345-dcbee495-6d5e-6ed48124632c : data : : 1307103848 : "hi, how are ..."

部分鍵掃瞄

hbase 的掃瞄功能和基於 htable 的api更適合在高表上篩選資料,可以通過只包含部分鍵的掃瞄檢索資料,同時不丟失查詢的粒度。

在上面的例子中,在寬表的場景中,可以使用使用者id取到使用者行,並通過列名(訊息id)篩選資料。在高表的場景中,需要有使用者id和訊息id同時確定一行資料,否則不能找到乙個特定的郵件。可以使用包含部分鍵的掃瞄解決這個問題:掃瞄操作設定乙個開始和結束的使用者id(預設結果是不包含終止鍵的,所以結束鍵一般需要設為 userid + 1)。

我們可以使用包含部分鍵的掃瞄機制設計出比較有效的左對齊索引,當乙個欄位被加到行鍵中,就多了乙個可以檢索的維度(注意檢索必須包含從左到右的某幾個字段,如果只檢索中間的某個字段,效率還是不高):---

需要保證行鍵中的每個欄位都設定乙個固定的長度,並且每個欄位的值都補齊到這個長度,這樣才能保證字典序按預期排列。如果使用者id:2和10,期望得到的行鍵是:"02***x"、"10***x",與預期一致。如果不補齊長度,得到的行鍵為:"10***x"、"2***x",與預期不同。

上面設計的行鍵可以實現一下索引:

掃瞄乙個特定使用者下的所有訊息

- 掃瞄乙個特定使用者下特定日期的所有訊息

-- 掃瞄乙個特定使用者特定日期下的指定訊息的全部內容

--- 掃瞄乙個特定使用者特定日期下的指定訊息的乙個附件

類似的,可以控制每個欄位的內容以達到控制排序的目的。例如可以把日期反轉,得到按日期降序排列的效果:long.max_value -

行鍵的設計並非有固定模式,需要視業務需要而定,例如上面的行鍵設計看似不錯,但是如果業務上需要統一修改乙個使用者所有郵件或郵件所有附件的屬性值,是無法保證原子性的操作的(hbase 只支援行資料原子操作),寬表可能更加適合。

分頁使用掃瞄可以很方便的遍歷查詢資料子集的行。可以設定起始鍵和終止鍵限制掃瞄的範圍,同時在 client 端新增 offset 和 limit 引數篩選資料。

具體過程如下:

在起始鍵位置開啟乙個掃瞄器

跳過 offset 數目的行

讀取 limit 數碼的行,並返回

關閉掃瞄器

通過不通的行鍵設計,可以實現多種方式的子集掃瞄和分也。例如按時間逆序排列,總是會先讀到最新到達的資料。

時間序列

當處理流式資料時,最常見的資料就是按時間序列組織的資料。資料可能來自感測器,監控系統,實時交易系統等。這些資料的特點是行鍵都代表了事件發生的時間。由於 hbase 的資料組織方式,這樣的資料在儲存時會出現乙個問題:資料熱點問題,由於業務的特性在某些特定範圍內資料量會非常大,會造成 region 的資料量分布不均勻,同時資料寫入會集中到特定的 region 上,導致效能下降。

為了解決這類問題,需要將資料能夠更均勻的分散到各個 region 上,在此介紹幾種方法:

salting 方式

可以使用 salting 字首來保證資料分散到所有 region 上:

byte prefix = (byte) (long.hashcode(timestamp) % );

byte rowkey = bytes.add(bytes.tobytes(prefix), bytes.tobytes(timestamp);

上面字首的計算方法,利用時間戳的離散雜湊值,並假設 regionserver 數量固定的情況,能夠使資料均勻的分布在各個 region 上。

缺點是,單次對原始的行鍵進行範圍掃瞄(原始連續的行鍵新增了隨機字首後,離散到各個 region 中)效率比較低,但是可以通過多執行緒並行讀取的方式提高效率。

字段交換/提公升權重

如果行鍵設計包含了多個字段,可以將時間戳字段(如果是乙個字段,或其他不離散的第乙個字段)在不影響業務的前提下,調整位置。如果行鍵只包含時間戳,可以將其他字段提取出來放到行鍵的第一位。

通過指標id將資料離散,得到與 salting 字首相同的效果。

隨機化另一種完全不同的方式是將行鍵隨機化(雜湊或md5演算法):

byte rowkey = md5(timestamp)

能夠將行鍵分散到所有 region 上,缺點就是不能在按照順序進行掃瞄,不適用與時序的資料。該方式比較適合隨機讀寫的場景。

hbase

使用時需要在行鍵設計和讀寫效能上找到平衡點,如上圖與讀寫方式的關係。

references:

《hbase 權威指南》

前端 EXTJS grid 元件更改行高

本來在網上查到了一些方法 但不知道是不是版本問題還是什麼 總之就是沒有效果 後來經過一系列的更改實驗 網路資料其一 其中我不知道這個作者是筆誤還是什麼意思 設定為 top 居然還注釋是 垂直居中 x grid row td,x grid summary row td網路資料其二 在grid後面加了個...

HBase行鍵設計

唯一原則 行鍵對應關係型資料庫的唯一鍵,系統設計之初必須考慮有足夠的唯一行鍵去支援業務的資料量。長度原則 長度適中,一般從幾十到一百位元組,建議使用定長,方便從行鍵提取所需資料,而無須查詢出資料內容以節省網路開銷。雜湊原則 避免遞增,否則讀寫負載都會集中在某個熱點分割槽,降低效能,甚至引起分割槽伺服...

iOS 動態更改APP(logo) icon

那這個功能是怎麼實現的 這個功能實現起來很簡單,但是對系統版本有要求,這個功能只能在ios 10及10以上才可以實現。其他情況下本人也用過,但是會出現閃退情況。首先我們要在plist檔案中配置 1 key icon files ios 5 value dictionary 2 接下來,開啟 icon...