HBase row key設計得不好、頻度各異的查詢類型,會導緻熱門資料集中坐落在某幾個Region上,造成Region熱點,叢集負載不均衡。
能采取哪些解決方案,首先要明确通路模式,然後針對性優化:
犧牲有序性,散列化row key。
如果不需要資料的有序性:
在row key首部增加原始row key的hash code,使資料均勻散列。
或者,将原始row key的MD5作為實際的row key。
對整個row key散列犧牲了有序性和根據字首比對進行範圍掃描的能力。
為此,我們也可以對row key的各個部分,分别求取MD5,再拼接起來,作為新的row key。這樣雖然仍不支援有序查詢,但是支援根據字首比對進行範圍掃描——根據row key字首的MD5,範圍掃描比對的行,傳回的是無序的資料。
不同通路模式的資料,不要混雜在一張表裡。
一個店鋪有哪些商品(row key是store id + product id) 和 一種商品有哪些店鋪在出售(row key是product id + store id),這兩種行,不要放在一張表裡。
因為業務應用的以上兩種查詢,其執行頻率會有很大差别。如果這兩種行,在一張表裡,其中一種更頻繁的查詢,自然會導緻整張表中的一類row key成為熱點資料。
是以,要拆成兩張表,讓HBase有自由度獨立管理兩張表的region,獨立進行region的拆分,保持負載均衡。
二級索引的熱點
我們根據查詢條件有哪些字段,建構出二級索引,二級索引的值就是資料表的row key。那麼對于經常執行的查詢條件,會集中通路二級索引的一部分行,就造成了二級索引的熱點區域。
舉個例子,以時間戳作為二級索引的key,支援時間範圍查找,那麼寫入最新的資料、查詢最新的資料,很容易導緻最後一個region成為熱點。
為此,我們要影響二級索引的分片政策。我學習到了兩種方案:
方案一:salting
在以時間戳作為二級索引的例子中,計算:
···
salt = timestamp.hashCode() % region server個數
将以上salt作為時間戳二級索引的字首。這樣打亂了原先的二級索引分片政策,使得負載均衡。
salt的取值範圍是[0, region server個數)。 是以,查詢時,我們的應用邏輯,需要對每一個salt的取值,發起一次查詢請求,以salt值作為scan的row key的字首。然後,将這些查詢的結果合并傳回。
salt技術有一個問題——當region server數量變化時,row key字首中的salt沒有相應更新。
方案二 by 360
其核心思想是,索引和資料保證在同一張表的同一個region裡。這是通過将region的start row key作為索引row key的首部字首實作的。索引和資料,在同一行的不同column family中。當region分裂以平衡負載時,索引和資料共同分裂。二級索引的通路負載會和被索引的資料一樣均衡。因為資料和它的二級索引總是在同一個region裡的。
這種方案能處理region分裂、region server個數發生變化的情形。