一、查詢最左比對原則
假設查詢包含3個次元:uid,city,age, 将rowkey的格式為: uid_city_age 則以下次元的查詢都會比較高效
- 通過uid查詢
- 通過uid+city查詢
- 通過uid、city和age查詢
而以下次元的查詢則會相對低效一些而以下次元的查詢則會相對低效一些
- 通過city查詢
- 通過age查詢
- 通過city + age查詢
- 通過uid + age查詢
其中1、2、3将會是全表掃描操作,是以非常低效,但是如果有這樣的查詢需求怎麼辦?可以考慮引入phoenix二級索引。
二、避免熱點Region出現
熱點Region容易導緻讀寫出現性能瓶頸,是以通常需要對原始rowkey做一些特殊處理,來保證資料寫入能夠均勻散列
通常的做法有以下幾種:
-
将rowkey進行反轉(适用于自增性質的rowkey)
比如訂單id這個字段是每次加1自動增長的,如果直接将其作為rowkey來進行寫入将會産生寫入熱點(相鄰rowkey全部寫入到了一個Region裡),而反轉之後的寫入是可以散列分布到每一個Region的。
針對反轉操作,hbase用戶端SDK提供了com.meituan.service.hbase.HBaseUtil#reverse實用方法來供業務調用使用
- 在原始rowkey之前添加一個hash字首
适用于以下業務場景
(1). 原始rowkey的字首都比較相似,很難通過字首來合理劃分區間
(2). rowkey的字首區間不固定或很難确定,導緻沒有辦法做預定義分區處理
(3). 同樣适用于自增性質的rowkey
-
對表格進行加鹽處理
适用場景:rowkey包含時間戳資訊,比如格式為pigeId_timestamp,并且有個别pigeId的吞吐非常龐大,單Region已經無法承載相應的寫入需求。
此時需要對原始rowkey進行加鹽處理,将同一個pigeId的資料分散到不同的Region中進行寫入。
加鹽處理與加hash字首的處理方式比較類似,都是在原始rowkey之前加一個散列字首,但是應用場景卻不相同。
拿格式為pigeId_timestamp的rowkey舉例,如果單個pigeId的吞吐不大,單Region能夠滿足吞吐需求,那麼隻需要針對pigeId進行hash即可,
将rowkey轉換成hash(pigeId)_pigeId_timestamp格式,即方案2的處理方式。
而如果單Region滿足不了個别pigeId的吞吐需求則需要對pigeId_timestamp整體進行hash處理,将rowkey轉換成hash(pigeId_timestamp)_pigeId_timestamp格式。
不同格式的rowkey在查詢處理上會有以下不同,比如想要查詢某個pigeId在指定時間範圍内的資料記錄。
(1) 如果格式為hash(pigeId)_pigeId_timestamp,隻需要掃描個别Region即可,因為相同時間範圍内的記錄是順序寫入到同一Region的
(2) 而如果格式為hash(pigeId_timestamp)_pigeId_timestamp,則需要對全部Region進行掃描,因為相同時間範圍内的記錄是打散到每一個Region上的
針對該類型的查詢請求,hbase的SDK提供了parScan方法,會并行掃描每一個Region,然後将查詢結果進行聚合傳回給用戶端。
目前絕大部分業務采用方案2即可避免熱點問題,當吞吐量變的十分巨大時建議考慮方案3