Hbase中的region和rowkey

来源:https://www.cnblogs.com/paopaoT/archive/2023/06/13/17478948.html
-Advertisement-
Play Games

# region Region是HBase數據管理的基本單位,region有一點像關係型數據的分區。 Region中存儲這用戶的真實數據,而為了管理這些數據,HBase使用了RegionSever來管理region。 ## region的分配 一個表中可以包含一個或多個Region。 每個Regio ...


region

Region是HBase數據管理的基本單位,region有一點像關係型數據的分區。
Region中存儲這用戶的真實數據,而為了管理這些數據,HBase使用了RegionSever來管理region。

region的分配

一個表中可以包含一個或多個Region。

每個Region只能被一個RS(RegionServer)提供服務,RS可以同時服務多個Region,來自不同RS上的Region組合成表格的整體邏輯視圖。

regionServer其實是hbase的服務,部署在一臺物理伺服器上,region有一點像關係型數據的分區,數據存放在region中,當然region下麵還有很多結構,確切來說數據存放在memstore和hfile中。我們訪問hbase的時候,先去hbase 系統表查找定位這條記錄屬於哪個region,然後定位到這個region屬於哪個伺服器,然後就到哪個伺服器裡面查找對應region中的數據

region結構

image

數據的寫入

image

Memstore Flush流程

flus流程分為三個階段:

  1. prepare階段:遍歷當前 Region中所有的 MemStore ,將 MemStore 中當前數據集 CellSkpiListSet 做一個快照 snapshot;然後再新建一個 CellSkipListSet。後期寫入的數據都會寫入新的 CellSkipListSet 中。prepare 階段需要加一把 updataLock 對寫請求阻塞,結束之後會釋放該鎖。因為此階段沒有任何費時操作,因此鎖持有時間很短

  2. flush階段:遍歷所有 MemStore,將 prepare 階段生成的snapshot 持久化為臨時文件,臨時文件會統一放到目錄.tmp下。這個過程因為涉及到磁碟 IO 操作,因此相對耗時

  3. commit階段:遍歷所有 MemStore,將flush階段生成的臨時文件移動到指定的 ColumnFamily 目錄下,針對 HFile生成對應的 StoreFile 和 Reader,把 StoreFile 添加到 HStore 的 storefiles 列表中,最後再清空 prepare 階段生成的 snapshot快照

Compact 合併機制

hbase中的合併機制分為自動合併和手動合併

自動合併:

  • minor compaction 小合併
  • major compacton 大合併

minor compaction(小合併)
將 Store 中多個 HFile 合併為一個相對較大的 HFile 過程中會選取一些小的、相鄰的 StoreFile 將他們合併成一個更大的 StoreFile,對於超過 TTL 的數據、更新的數據、刪除的數據僅僅只是做了標記,並沒有進行物理刪除。一次 minor compaction 過後,storeFile會變得更少並且更大,這種合併的觸發頻率很高

小合併的觸發方式:
memstore flush會產生HFile文件,文件越來越多就需要compact.每次執行完Flush操作之後,都會對當前Store中的文件數進行判斷,一旦文件數大於配置3,就會觸發compaction。compaction都是以Store為單位進行的,而在Flush觸發條件下,整個Region的所有Store都會執行compact

後臺線程周期性檢查
檢查周期可配置:
hbase.server.thread.wakefrequency 預設10000毫秒)
hbase.server.compactchecker.interval.multiplier 預設1000
CompactionChecker大概是2hrs 46mins 40sec 執行一次

<!--表示至少需要三個滿足條件的store file時,minor compaction才會啟動-->
<property>
        <name>hbase.hstore.compactionThreshold</name>
        <value>3</value>
</property>

<!--表示一次minor compaction中最多選取10個store file-->
<property>
        <name>hbase.hstore.compaction.max</name>
        <value>10</value>
</property>

<!--預設值為128m,
表示文件大小小於該值的store file 一定會加入到minor compaction的store file中
-->
<property>
        <name>hbase.hstore.compaction.min.size</name>
        <value>134217728</value>
</property>

<!--預設值為LONG.MAX_VALUE,表示文件大小大於該值的store file 一定會被minor compaction排除-->
<property>
        <name>hbase.hstore.compaction.max.size</name>
        <value>9223372036854775807</value>
</property>

major compaction(大合併)

合併 Store 中所有的 HFile 為一個 HFile,將所有的 StoreFile 合併成為一個 StoreFile,這個過程中還會清理三類無意義數據:被刪除的數據、TTL過期數據、版本號超過設定版本號的數據。合併頻率比較低,預設7天執行一次,並且性能消耗非常大,建議生產關閉(設置為0),在應用空間時間手動觸發。一般是可以手動控制進行合併,防止出現在業務高峰期。

線程先檢查小文件數是否大於配置3,一旦大於就會觸發compaction。
大文件周期性合併成Major Compaction
如果不滿足,它會接著檢查是否滿足major compaction條件
如果當前store中hfile的最早更新時間早於某個值mcTime就會觸發major compaction 
(預設7天觸發一次,可配置手動觸發)

<!--預設值為7天進行一次大合併,-->
<property>
        <name>hbase.hregion.majorcompaction</name>
        <value>604800000</value>
</property>

手動合併

一般來講,手動觸發compaction通常是為了執行major compaction,一般有這些情況需要手動觸發合併是因為很多業務擔心自動maior compaction影響讀寫性能,因此會選擇低峰期手動觸發也有可能是用戶在執行完alter操作之後希望立刻生效,執行手動觸發maiorcompaction:

# 造數據
truncate 'doit:test'
put 'doit:test','001','f1:name','zss'
put 'doit:test','002','f1:name','zss'
put 'doit:test','003','f1:name','zss'
put 'doit:test','004','f1:name','zss'
flush 'doit:test'                    
put 'doit:test','005','f1:name','zss'
put 'doit:test','006','f1:name','zss'
put 'doit:test','007','f1:name','zss'
put 'doit:test','008','f1:name','zss'
flush 'doit:test'                    
put 'doit:test','009','f1:name','zss'
put 'doit:test','010','f1:name','zss'
put 'doit:test','011','f1:name','zss'
put 'doit:test','012','f1:name','zss'
flush 'doit:test'
put 'doit:test','013','f1:name','zss'
put 'doit:test','014','f1:name','zss'
put 'doit:test','015','f1:name','zss'
put 'doit:test','016','f1:name','zss'
flush 'doit:test'
put 'doit:test','017','f1:name','zss'
put 'doit:test','018','f1:name','zss'
put 'doit:test','019','f1:name','zss'
put 'doit:test','020','f1:name','zss'
flush 'doit:test'
put 'doit:test','021','f1:name','zss'
put 'doit:test','022','f1:name','zss'
put 'doit:test','023','f1:name','zss'
put 'doit:test','024','f1:name','zss'
flush 'doit:test'
put 'doit:test','025','f1:name','zss'
put 'doit:test','026','f1:name','zss'
put 'doit:test','027','f1:name','zss'
put 'doit:test','028','f1:name','zss'
flush 'doit:test'
put 'doit:test','021','f1:name','zss'
put 'doit:test','022','f1:name','zss'
put 'doit:test','023','f1:name','zss'
put 'doit:test','024','f1:name','zss'
flush 'doit:test'
put 'doit:test','021','f1:name','zss'
put 'doit:test','022','f1:name','zss'
put 'doit:test','023','f1:name','zss'
put 'doit:test','024','f1:name','zss'
flush 'doit:test'
put 'doit:test','021','f1:name','zss'
put 'doit:test','022','f1:name','zss'
put 'doit:test','023','f1:name','zss'
put 'doit:test','024','f1:name','zss'
flush 'doit:test'

put 'doit:test','021','f1:name','zss'
put 'doit:test','022','f1:name','zss'
put 'doit:test','023','f1:name','zss'
put 'doit:test','024','f1:name','zss'
flush 'doit:test'

# 每次flush一下都會在底層生成一個小文件

image

##使用major_compact命令
major_compact tableName

major_compact 'doit:test'

image

region的拆分

region中存儲的是一張表的數據,當region中的數據條數過多的時候,會直接影響查詢效率。當region過大的時候,region會被拆分為兩個region,HMaster會將分裂的region分配到不同的regionserver上,這樣可以讓請求分散到不同的RegionServer上,已達到負載均衡 , 這也是HBase的一個優點

region的拆分策略

  1. ConstantSizeRegionSplitPolicy:0.94版本前,HBase region的預設切分策略

當region中最大的store大小超過某個閾值(hbase.hregion.max.filesize=10G)之後就會觸發切分,一個region等分為2個region。

但是在生產線上這種切分策略卻有相當大的弊端(切分策略對於大表和小表沒有明顯的區分):
1.閾值(hbase.hregion.max.filesize)設置較大對大表比較友好,但是小表就有可能不會觸發分裂,極端情況下可能就1個,形成熱點,這對業務來說並不是什麼好事。
2.如果設置較小則對小表友好,但一個大表就會在整個集群產生大量的region,這對於集群的管理、資源使用、failover來說都不是一件好事。

  1. IncreasingToUpperBoundRegionSplitPolicy:0.94版本~2.0版本預設切分策略

總體看和ConstantSizeRegionSplitPolicy思路相同,一個region中最大的store大小大於設置閾值就會觸發切分。 但是這個閾值並不像ConstantSizeRegionSplitPolicy是一個固定的值,而是會在一定條件下不斷調整,調整規則和region所屬表在當前regionserver上的region個數有關係.

region split閾值的計算公式是:
1.設regioncount:是region所屬表在當前regionserver上的region的個數
2.閾值 = regioncount^3 * 128M * 2,當然閾值並不會無限增長,最大不超過MaxRegionFileSize(10G),當region中最大的store的大小達到該閾值的時候進行region split

例如:
• 第一次split閾值 = 1^3 * 256 = 256MB
• 第二次split閾值 = 2^3 * 256 = 2048MB
• 第三次split閾值 = 3^3 * 256 = 6912MB
• 第四次split閾值 = 4^3 * 256 = 16384MB > 10GB,因此取較小的值10GB
• 後面每次split的size都是10GB了

特點
• 相比ConstantSizeRegionSplitPolicy,可以自適應大表、小表;
• 在集群規模比較大的情況下,對大表的表現比較優秀
• 對小表不友好,小表可能產生大量的小region,分散在各regionserver上
• 小表達不到多次切分條件,導致每個split都很小,所以分散在各個regionServer上

  1. SteppingSplitPolicy:2.0版本預設切分策略

相比 IncreasingToUpperBoundRegionSplitPolicy 簡單了一些 region切分的閾值依然和待分裂region所屬表在當前regionserver上的region個數有關係
• 如果region個數等於1,切分閾值為flush size 128M * 2
• 否則為MaxRegionFileSize。

這種切分策略對於大集群中的大表、小表會比 IncreasingToUpperBoundRegionSplitPolicy 更加友好,小表不會再產生大量的小region,而是適可而止。

  1. KeyPrefixRegionSplitPolicy

根據rowKey的首碼對數據進行分區,這裡是指定rowKey的前多少位作為首碼,比如rowKey都是16位的,指定前5位是首碼,那麼前5位相同的rowKey在相同的region中

  1. DelimitedKeyPrefixRegionSplitPolicy

保證相同首碼的數據在同一個region中,例如rowKey的格式為:userid_eventtype_eventid,指定的delimiter為 _ ,則split的的時候會確保userid相同的數據在同一個region中。 按照分隔符進行切分,而KeyPrefixRegionSplitPolicy是按照指定位數切分

  1. BusyRegionSplitPolicy

按照一定的策略判斷Region是不是Busy狀態,如果是即進行切分
如果你的系統常常會出現熱點Region,而你對性能有很高的追求,那麼這種策略可能會比較適合你。它會通過拆分熱點Region來緩解熱點Region的壓力,但是根據熱點來拆分Region也會帶來很多不確定性因素,因為你也不知道下一個被拆分的Region是哪個

  1. DisabledRegionSplitPolicy:不啟用自動拆分, 需要指定手動拆分

手動合併拆分region

手動合併

hbase(main):025:0> list_regions 'doit:test'
                 SERVER_NAME |                                                          REGION_NAME |  START_KEY |    END_KEY |  SIZE |   REQ |   LOCALITY |
 --------------------------- | -------------------------------------------------------------------- | ---------- | ---------- | ----- | ----- | ---------- |
 linux03,16020,1684200651855 |           doit:test,,1684205468848.920ae3e043ad95890c4f5693cb663bc5. |            | rowkey_010 |     0 |     0 |        0.0 |
 linux01,16020,1684205091382 | doit:test,rowkey_010,1684207066858.5e04eb75e5510ad65a0f3001de3c7aa0. | rowkey_010 | rowkey_015 |     0 |     0 |        0.0 |
 linux02,16020,1684200651886 | doit:test,rowkey_015,1684207066858.ed1b328ca4c485d4fa429922f6c18f0b. | rowkey_015 | rowkey_020 |     0 |     0 |        0.0 |
 linux02,16020,1684200651886 | doit:test,rowkey_020,1684205468848.25d62e8cc2fdaecec87234b8d28f0827. | rowkey_020 | rowkey_030 |     0 |     0 |        0.0 |
 linux03,16020,1684200651855 | doit:test,rowkey_030,1684205468848.2b0468e6643b95159fa6e210fa093e66. | rowkey_030 | rowkey_040 |     0 |     0 |        0.0 |
 linux01,16020,1684205091382 | doit:test,rowkey_040,1684205468848.fb12c09c7c73cfeff0bf79b5dda076cb. | rowkey_040 |            |     0 |     0 |        0.0 |
 6 rows
Took 0.0299 seconds
hbase(main):026:0> merge_region 'doit:test,,1684205468848.920ae3e043ad95890c4f5693cb663bc5.','doit:test,rowkey_010,1684207066858.5e04eb75e5510ad65a0f3001de3c7aa0.'
Took 1.2638 seconds
hbase(main):027:0> list_regions 'doit:test'
                 SERVER_NAME |                                                          REGION_NAME |  START_KEY |    END_KEY |  SIZE |   REQ |   LOCALITY |
 --------------------------- | -------------------------------------------------------------------- | ---------- | ---------- | ----- | ----- | ---------- |
 linux03,16020,1684200651855 |           doit:test,,1684207066859.cdc1226d634c0cf16f58832637f485b6. |            | rowkey_015 |     0 |     0 |        0.0 |
 linux02,16020,1684200651886 | doit:test,rowkey_015,1684207066858.ed1b328ca4c485d4fa429922f6c18f0b. | rowkey_015 | rowkey_020 |     0 |     0 |        0.0 |
 linux02,16020,1684200651886 | doit:test,rowkey_020,1684205468848.25d62e8cc2fdaecec87234b8d28f0827. | rowkey_020 | rowkey_030 |     0 |     0 |        0.0 |
 linux03,16020,1684200651855 | doit:test,rowkey_030,1684205468848.2b0468e6643b95159fa6e210fa093e66. | rowkey_030 | rowkey_040 |     0 |     0 |        0.0 |
 linux01,16020,1684205091382 | doit:test,rowkey_040,1684205468848.fb12c09c7c73cfeff0bf79b5dda076cb. | rowkey_040 |            |     0 |     0 |        0.0 |
 5 rows
Took 0.0271 seconds

手動拆分

hbase(main):029:0> list_regions 'doit:test'
                 SERVER_NAME |                                                          REGION_NAME |  START_KEY |    END_KEY |  SIZE |   REQ |   LOCALITY |
 --------------------------- | -------------------------------------------------------------------- | ---------- | ---------- | ----- | ----- | ---------- |
 linux03,16020,1684200651855 |           doit:test,,1684207066860.8ebf4555c58bd0e5fedae5d4efbe4235. |            | rowkey_030 |     0 |     0 |        0.0 |
 linux03,16020,1684200651855 | doit:test,rowkey_030,1684205468848.2b0468e6643b95159fa6e210fa093e66. | rowkey_030 | rowkey_040 |     0 |     0 |        0.0 |
 linux01,16020,1684205091382 | doit:test,rowkey_040,1684205468848.fb12c09c7c73cfeff0bf79b5dda076cb. | rowkey_040 |            |     0 |     0 |        0.0 |
 3 rows
Took 0.0329 seconds
hbase(main):030:0> split 'doit:test,,1684207066860.8ebf4555c58bd0e5fedae5d4efbe4235.','rowkey_025'
Took 0.1179 seconds
hbase(main):031:0> list_regions 'doit:test'
                 SERVER_NAME |                                                          REGION_NAME |  START_KEY |    END_KEY |  SIZE |   REQ |   LOCALITY |
 --------------------------- | -------------------------------------------------------------------- | ---------- | ---------- | ----- | ----- | ---------- |
 linux02,16020,1684200651886 |           doit:test,,1684207502853.af0819bd7f6daa9db2a8f994fb41682d. |            | rowkey_025 |     0 |     0 |        0.0 |
 linux02,16020,1684200651886 | doit:test,rowkey_025,1684207502853.80d7feace447978ffe4a54418a20afd0. | rowkey_025 | rowkey_030 |     0 |     0 |        0.0 |
 linux03,16020,1684200651855 | doit:test,rowkey_030,1684205468848.2b0468e6643b95159fa6e210fa093e66. | rowkey_030 | rowkey_040 |     0 |     0 |        0.0 |
 linux01,16020,1684205091382 | doit:test,rowkey_040,1684205468848.fb12c09c7c73cfeff0bf79b5dda076cb. | rowkey_040 |            |     0 |     0 |        0.0 |
 4 rows
Took 0.0179 seconds
hbase(main):032:0> split 'doit:test,,1684207502853.af0819bd7f6daa9db2a8f994fb41682d.','rowkey_015'
Took 0.1262 seconds
hbase(main):033:0> list_regions 'doit:test'
                 SERVER_NAME |                                                          REGION_NAME |  START_KEY |    END_KEY |  SIZE |   REQ |   LOCALITY |
 --------------------------- | -------------------------------------------------------------------- | ---------- | ---------- | ----- | ----- | ---------- |
 linux02,16020,1684200651886 |           doit:test,,1684207546572.0f550ec8fa1af0ab9e73032d224d9f00. |            | rowkey_015 |     0 |     0 |        0.0 |
 linux02,16020,1684200651886 | doit:test,rowkey_015,1684207546572.09a2022c54dfef68866ac73e3f78bc70. | rowkey_015 | rowkey_025 |     0 |     0 |        0.0 |
 linux02,16020,1684200651886 | doit:test,rowkey_025,1684207502853.80d7feace447978ffe4a54418a20afd0. | rowkey_025 | rowkey_030 |     0 |     0 |        0.0 |
 linux03,16020,1684200651855 | doit:test,rowkey_030,1684205468848.2b0468e6643b95159fa6e210fa093e66. | rowkey_030 | rowkey_040 |     0 |     0 |        0.0 |
 linux01,16020,1684205091382 | doit:test,rowkey_040,1684205468848.fb12c09c7c73cfeff0bf79b5dda076cb. | rowkey_040 |            |     0 |     0 |        0.0 |
 5 rows
Took 0.0241 seconds

bulkLoad實現批量導入

bulkloader : 一個用於批量快速導入數據到hbase的工具/方法

用於已經存在一批巨量靜態數據的情況!如果不用bulkloader工具,則只能用rpc請求,一條一條地通過rpc提交給regionserver去插入,效率極其低下

原理

image
相比較於直接寫HBase,BulkLoad主要是繞過了寫WAL日誌這一步,還有寫Memstore和Flush到磁碟,從理論上來分析性能會比Put快!

importTsv工具

原理:
Importtsv是hbase自帶的一個 csv文件--》HFile文件 的工具,它能將csv文件轉成HFile文件,併發送給regionserver。它的本質,是內置的一個將csv文件轉成hfile文件的mr程式!

# CSV轉HFILE的命令示例如下:
# 001,北戴河,河北省,河北省北戴河昌平區沙河鎮賦騰國際創客中心A座4018室
hbase  org.apache.hadoop.hbase.mapreduce.ImportTsv \
-Dimporttsv.separator=, \
-Dimporttsv.columns='HBASE_ROW_KEY,f:city,f:province,x:address'  \
-Dimporttsv.bulk.output=/tsv/output \
user_info \
/tsv/input

ImportTsv命令的參數說明如下:
-Dimporttsv.skip.bad.lines=false - 若遇到無效行則失敗
-Dimporttsv.separator=, - 使用特定分隔符,預設是tab也就是\t
-Dimporttsv.timestamp=currentTimeAsLong - 使用導入時的時間戳
-Dimporttsv.mapper.class=my.Mapper - 使用用戶自定義Mapper類替換TsvImporterMapper
-Dmapreduce.job.name=jobName - 對導入使用特定mapreduce作業名
-Dcreate.table=no - 避免創建表,註:如設為為no,目標表必須存在於HBase中
-Dno.strict=true - 忽略HBase表列族檢查。預設為false
-Dimporttsv.bulk.output=/user/yarn/output 作業的輸出目錄

hfile

邏輯數據組織格式

image

  • Scanned block section:表示順序掃描HFile時(rile時(包含所有需要被讀取的數據)所有的數據塊將會被讀取,包括Leaf Index Block和Bloom Block;
  • Non-scanned block section:HFile順序掃描的時候該部分數據不會被讀取,主要包括Meta Block和Intermediate Level Data Index Blocks兩部分;
  • Load-on-open-section:這部分數據在HBase的region server啟動時,需要載入到記憶體中。包括FileInfo、Bloom filter block、data block index和meta block index等各種索引的元數據信息;
  • Trailer:這部分主要記錄了HFile的基本信息、各個部分的偏移值和定址信息。
  • Data Block:主要存儲用戶的key,value信息
  • Meta Block:記錄布隆過濾器的信息
  • Root Data Index:DataBlock的根索引以及MetaBlock和Bloom Filter的索引
  • Intermediate Level Index:DataBlock的第二層索引
  • Leaf Level Index:DataBlock的第三層索引,即索引數的葉子節點
  • Fileds for midKey:這部分數據是Optional的,保存了一些midKey信息,可以快速地定位到midKey,常常在HFileSplit的時候非常有用
  • MetaIndex:即meta的索引數據,和data index類似,但是meta存放的是BloomFilter的信息
  • FileInfo:保存了一些文件的信息,如lastKey,avgKeylen,avgValueLen等等
  • Bloom filter metadata:是布隆過濾器的索引

物理數據結構圖

image

數據的讀取

image

  1. Client訪問zookeeper,獲取hbase:meta所在RegionServer的節點信息

  2. Client訪問hbase:meta所在的RegionServer,獲取hbase:meta記錄的元數據後先載入到記憶體中,然後再從記憶體中根據需要查詢的RowKey查詢出RowKey所在的Region的相關信息(Region所在RegionServer)

  3. Client訪問RowKey所在Region對應的RegionServer,發起數據讀取請求

  4. 讀取memstore中的數據,看是否有key對應的value的值

  5. 不管memstore中有沒有值,都需要去讀取Hfile中的數據(再讀取Hfile中首先通過索引定位到data block)

  6. 判斷cache block中中是否已經載入過需要從文件中讀取的bloom block和data block,如果載入過了,就直接讀取cache block中的數據,如果沒有,就讀取文件中的block數據

  7. 將memstore和Hfile中讀取的數據彙總取正確的數據返回給客戶端

rowkey的設計

設計的三大原則

  1. Rowkey長度原則

Rowkey是一個二進位碼流,Rowkey的長度被很多開發者建議設計在10-100個位元組,不過建議是越短越好,不要超過16個位元組

原因如下:

  • 數據的持久化文件HFile中是按照KeyValue存儲的,如果Rowkey過長比如100個位元組,1000萬列數據光Rowkey就要占用100*1000萬=10億個位元組,將近1G數據,這會極大影響Hfile的存儲效率;
  • MemStore將緩存部分數據到記憶體,如果Rowkey欄位過長記憶體的有效利用率降低,系統將無法緩存更多的數據,這會降低檢索效率,因此Rowkey的位元組長度越短越好。
  • 目前操作系統一般都是64位系統,記憶體8位元組對齊,空值在16個位元組,8位元組的整數倍利用操作系統的最佳特性。
  1. Rowkey散列原則

如果Rowkey是按時間戳的方式遞增,因為rowkey是按照字典順序排序的,這樣會出現大量的數據插入到一個reion中,而其他的region相對比較空閑從而造成熱點問題,所以儘量不要將開頭相同的內容作為rowkey造成熱點問題,可以將時間戳反轉後在作為rowkey。

  1. Rowkey唯一原則

必須在設計Rowkey上保證其唯一性。否則前面插入的數據將會被覆蓋。

常見的避免熱點的方法以及它們的優缺點

加鹽

這裡所說的加鹽不是密碼學中的加鹽,而是在rowkey的前面增加隨機數,具體就是給rowkey分配一個隨機首碼以使得它和之前的rowkey的開頭不同。分配的首碼種類數量應該和你想使用數據分散到不同的region的數量一致。加鹽之後的rowkey就會根據隨機生成的首碼分散到各個region上,以避免熱點。

哈希

哈希會使同一行永遠用一個首碼加鹽。哈希也可以使負載分散到整個集群,但是讀卻是可以預測的。使用確定的哈希可以讓客戶端重構完整的rowkey,可以使用get操作准確獲取某一個行數據

反轉

第三種防止熱點的方法時反轉固定長度或者數字格式的rowkey。這樣可以使得rowkey中經常改變的部分(最沒有意義的部分)放在前面。這樣可以有效的隨機rowkey,但是犧牲了rowkey的有序性。
比如手機號的反轉,時間戳的反轉,當一個連續遞增的數字類型想要作為rowkey時,可以用一個很大的數去減這個rowkey,反轉後再當成rowkey


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • > 註:本文隸屬於《理解ASP.NET Core》系列文章,請查看置頂博客或[點擊此處查看全文目錄](https://www.cnblogs.com/xiaoxiaotank/p/15185288.html) # 概述 在眾多知名品牌的網站中,比如微軟官網、YouTube等,我們經常可以見到“切換頁 ...
  • # Windows下安裝MySQL5.7.37 [TOC] [MySQL5.7.37下載地址](https://downloads.mysql.com/archives/community/?version=5.7.37&osva=Windows+%28x86%2C+64-bit%29) ##下載M ...
  • 目錄 一、入侵檢測系統 二、防火牆 三、防水牆 四、tcpdump抓包 五、實驗演示 1.SNAT 一、入侵檢測系統 特點:是不阻斷任何網路訪問,量化、定位來自內外網路的威脅情況, 主要以提供報警和事後監督為主,提供有針對性的指導措施和安全決策依據,類似於監控系統 二、防火牆 1.特點:隔離功能,工 ...
  • ## Core Dump 是什麼? Core Dump 是指進程異常退出時,操作系統將進程的記憶體狀態保存到文件中,這個文件就是 Core Dump 文件,中文一般翻譯為“核心轉儲”,哈,看起來還不如不翻譯。 我們可以認為 Core Dump 是“記憶體快照”,但實際上,除了記憶體信息之外,還有些關鍵的程 ...
  • CS5366內部集成了PD3.0及DSC decoder,應用Type-C轉HDMI2.0的顯示協議轉換晶元, 簡介: CS5366系列提供了USB Type-C(DisplayPort Alternate Mode)到HDMI轉換器的單晶元解決方案,帶有電源傳輸。CS5366系列支持一個USB T ...
  • 參考帖子:https://blog.csdn.net/freedompoi/article/details/122350866 目前想要實現STM32F4自帶的DMA雙緩衝區,嘗試過一版,結果不能預期,就使用了RxHalfCplt和RxCplt去實現DMA雙緩衝區的效果。 現在有時間了,又重新實現S ...
  • ## 介紹 windows系統自帶的遠程桌面連接相對市面上其他的遠程軟體而言有他的優點: 1. 免費 2. 連接穩定 3. 操作流暢,幾乎沒有遠程辦公的卡滯感 但是,唯一的缺點是連接的電腦之間必須使用一個區域網,也就是說比較適合校園、企業用戶。以校園為例進行講解。 ## 使用前提 1. 連接及被連接 ...
  • # 文件系統 > 文件是面向OS和麵向使用者而言的,對於人來說,音樂,圖片,文檔,游戲,軟體,郵件,等記錄信息的載體都被操作系統統稱為文件,而存儲在HDD(機械硬碟)和SSD(固態硬碟)里.因此文件是一種實體的抽象,而之所以文件需要文件名,是因為不同的文件需要進行相對應的區分,也就是文件名,而其中的 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...