溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

HBase中數(shù)據(jù)分布模型是怎么樣的

發(fā)布時間:2021-12-08 16:32:30 來源:億速云 閱讀:209 作者:小新 欄目:數(shù)據(jù)庫

這篇文章主要為大家展示了“HBase中數(shù)據(jù)分布模型是怎么樣的”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“HBase中數(shù)據(jù)分布模型是怎么樣的”這篇文章吧。

數(shù)據(jù)分布問題簡述

分布式產(chǎn)生的根源是“規(guī)模”,規(guī)??衫斫鉃橛嬎愫痛鎯Φ男枨蟆.?dāng)單機能力無法承載日益增長的計算存儲需求時,就要尋求對系統(tǒng)的擴展方法。通常有兩種擴展方式:提升單機能力(scale up),增加機器(scale out,水平擴展)。限于硬件技術(shù),單機能力的提升在一個階段內(nèi)是有上限的;而水平擴展在理論上可以是無限的,同時,也更廉價、更容易落地。水平擴展可以通過快速、簡單的“加機器”,有效解決業(yè)務(wù)快速增長的問題,這幾乎是現(xiàn)代分布式系統(tǒng)必備的能力。對于爆發(fā)式增長的業(yè)務(wù),水平擴展似乎是唯一可選擇的方案。

對于存儲系統(tǒng)而言,原本存儲在一臺機器上的數(shù)據(jù),現(xiàn)在要存放在多臺機器上。此時必須解決兩個問題:分片,復(fù)制。

  • 數(shù)據(jù)分片(sharding),又稱分區(qū)(partition),將數(shù)據(jù)集“合理的”拆分成多個分片,每臺機器負責(zé)其中若干個分片。以此來突破單機容量的限制,同時也提升了整體的訪問能力。另外,分片也降低了單個分片故障的影響范圍。

  • 數(shù)據(jù)復(fù)制(replica),也叫“副本”。分片無法解決單機故障丟數(shù)據(jù)的問題,所以,必然要通過冗余來解決系統(tǒng)高可用的問題。同時,副本機制也是提升系統(tǒng)吞吐、解決熱點問題的重要手段。

分片和副本是正交的,這意味著我們可以只使用其中一種或都使用,但通常都是同時使用的。因為分片解決的是規(guī)模和擴展性的問題,副本解決可靠、可用性的問題。對于一個生產(chǎn)可用的系統(tǒng),二者必須同時具備。

從使用者/客戶端的角度看,分片和副本可以歸結(jié)為同一個問題:請求路由,即請求應(yīng)該發(fā)送給哪臺機器來處理。

  • 讀數(shù)據(jù)時,能通過某種機制來確保有一個合適的分片/副本來提供服務(wù)

  • 寫數(shù)據(jù)時,能通過同樣的機制來確保寫到一個合適的地方,并確保副本的一致性

無論客戶端的請求是直達服務(wù)端(如HBase/cassandra),還是通過代理(如公有云上的基于gateway的訪問方式),請求路由都是分布式系統(tǒng)必須解決的問題。

無論是分片還是副本,本質(zhì)上都是數(shù)據(jù)分布的體現(xiàn)。下面我們來看HBase的數(shù)據(jù)分布模型。

HBase的數(shù)據(jù)分布模型

HBase的數(shù)據(jù)分片按表進行,以行為粒度,基于rowkey范圍進行拆分,每個分片稱為一個region。一個集群有多張表,每張表劃分為多個region,每臺服務(wù)器服務(wù)很多region。所以,HBase的服務(wù)器稱為RegionServer,簡稱RS。RS與表是正交的,即一張表的region會分布到多臺RS上,一臺RS也會調(diào)度多張表的region。如下圖所示:

HBase中數(shù)據(jù)分布模型是怎么樣的

“以行為粒度”,意思是行是region劃分的最小單位,即一行數(shù)據(jù)要么屬于A region,要么屬于Bregion,不會被拆到兩個region中去。(對行進行拆分的方式是“垂直分庫”,通常只能在業(yè)務(wù)層面進行,HBase是水平拆分)

HBase的副本機制是通過通過底層的HDFS實現(xiàn)的。所以,HBase的副本與分片是解耦的,是存儲計算分離的。這使得region可以在RS之間靈活的移動,而不需要進行數(shù)據(jù)遷移,這賦予了HBase秒級擴容的能力和極大的靈活性。

對于單個表而言,一個“好”的數(shù)據(jù)分布,應(yīng)該是每個region的數(shù)據(jù)量大小相近,請求量(吞吐)接近,每臺機器調(diào)度的region數(shù)量大致相同。這樣,這張表的數(shù)據(jù)和訪問能夠均勻的分布在整個集群中,從而得到最好的資源利用率和服務(wù)質(zhì)量,即達到負載均衡。當(dāng)集群進行擴容、縮容時,我們希望這種“均衡”能夠自動保持。如果數(shù)據(jù)分布未能實現(xiàn)負載均衡,則負載較高的機器很容易稱為整個系統(tǒng)的瓶頸,這臺機器的響應(yīng)慢,可能導(dǎo)致客戶端的大部分線程都在等待這臺機器返回,從而影響整體吞吐。所以,負載均衡是region劃分和調(diào)度的重要目標(biāo)。

這里涉及到3層面的負載均衡問題:

  • 數(shù)據(jù)的邏輯分布:即region劃分/分布,是rowkey到region的映射問題

  • 數(shù)據(jù)的物理分布:即region在RS上的調(diào)度問題

  • 訪問的分布:即系統(tǒng)吞吐(請求)在各個RS上的分布問題,涉及數(shù)據(jù)量和訪問量之間的關(guān)系,訪問熱點等。

可見,一行數(shù)據(jù)的分布(找到一行數(shù)據(jù)所在的RS),存在2個層級的路由:一是rowkey到region的路由,二是region到RS的路由。這一點是HBase能夠?qū)崿F(xiàn)靈活調(diào)度、秒級擴容的關(guān)鍵。后面我們會詳細討論。本文僅討論前面兩個問題,第三個問題放在后續(xù)的文章中討論。

基于rowkey范圍的region劃分

首先,我們來看數(shù)據(jù)的邏輯分布,即一張表如何劃分成多個region。

region劃分的粒度是行,region就是這個表中多個連續(xù)的行構(gòu)成的集合。行的唯一標(biāo)識符是rowkey,所以,可以將region理解為一段連續(xù)分布的rowkey的集合。所以,稱這種方式為基于rowkey范圍的劃分。

一個region負責(zé)的rowkey范圍是一個左閉右開區(qū)間,所以,后一個region的start key是前一個region的end key。注意,第一個region是沒有start key的,最后一個region是沒有end key的。這樣,這個表的所有region加在一起就能覆蓋任意的rowkey值域。如下圖所示:

HBase中數(shù)據(jù)分布模型是怎么樣的

上圖中,region1是第一個region,沒有startKey,region3是最后一個region,沒有endKey。圖中的region分布是比較均勻的,即每個region的行數(shù)是相當(dāng)?shù)?,那么,這個分布是怎么得到的呢?或者說,region的邊界是如何確定的?

一般來說,region的生成有3種方式:

  • 建表時進行預(yù)分區(qū):通過對rowkey進行預(yù)估,預(yù)先劃分好region

  • region分裂:手工分裂,或達到一定條件時自動分裂(如region大小超過一個閾值)

  • region合并:手工合并

建表時如果未顯式指定region分布,HBase就會只創(chuàng)建一個region,這個region自然也只能由一臺機器進行調(diào)度(后面會討論一個region由多個RS調(diào)度的情況)。那這個region的吞吐上限就是單機的吞吐上限。如果通過合理的預(yù)分區(qū)將表分成8個region,分布在8臺RS上,那整表的吞吐上限就是8臺機器的吞吐上限。

所以,為了使表從一開始就具備良好的吞吐和性能,實際生產(chǎn)環(huán)境中建表通常都需要進行預(yù)分區(qū)。但也有一些例外,比如無法預(yù)先對rowkey范圍進行預(yù)估,或者,不容易對rowkey范圍進行均勻的拆分,此時,也可以創(chuàng)建只有一個region的表,由系統(tǒng)自己分裂,從而逐漸形成一個“均勻的”region分布。

比如一張存儲多個公司的員工信息的表,rowkey組成是orgId + userid,其中orgId是公司的id。由于每個公司的人數(shù)是不確定的,同時也可能是差別很大的,所以,很難確定一個region中包含幾個orgId是合適的。此時,可以為其創(chuàng)建單region的表,然后導(dǎo)入初始數(shù)據(jù),隨著數(shù)據(jù)的導(dǎo)入進行region的自動分裂,通常都能得到比較理想的region分布。如果后續(xù)公司人員發(fā)生較大的變化,也可以隨時進行region的分裂與合并,來獲得最佳分布。

字典序與rowkey比較

上一節(jié)我們提到region的rowkey范圍是一個左閉右開區(qū)間,所有落在這個范圍的rowkey都屬于這個region。為了進行這個判斷,必須將其與這個region的起止rowkey進行比較。除了region歸屬的判斷,在region內(nèi)部,也需要依賴rowkey的比較規(guī)則來對rowkey進行排序。

很多人都會認為rowkey的比較非常簡單,沒有什么討論的必要。但正是因為簡單,它的使用才能靈活多樣,使得HBase具備無限的可能性。可以說,rowkey的比較規(guī)則是整個HBase數(shù)據(jù)模型的核心,直接影響了整個請求路由體系的設(shè)計、讀寫鏈路、rowkey設(shè)計、scan的使用等,貫穿整個HBase。對于用戶而言,深入理解這個規(guī)則及其應(yīng)用有助于做出良好的表設(shè)計,寫出精準(zhǔn)、高效的scan。

HBase的rowkey是一串二進制數(shù)據(jù),在Java中就是一個byte[],是一行數(shù)據(jù)的唯一標(biāo)識符。而業(yè)務(wù)的主鍵可能是有各種數(shù)據(jù)類型的,所以,這里要解決2個問題:

  • 將各種實際使用的數(shù)據(jù)類型與byte[]進行相互轉(zhuǎn)換

  • 保序:byte[]形式的rowkey的排序結(jié)果與原始數(shù)據(jù)的排序結(jié)果一致

rowkey的比較就是byte[]的比較,按字典序進行比較(二進制排序),簡單說,就是c語言中memcmp函數(shù)。通過下面的示例,我們通過排序結(jié)果來對這一比較規(guī)則以及數(shù)據(jù)類型轉(zhuǎn)換進行理解。

(1)ascii碼的大小比較1234 -> 0x31 32 33 345 -> 0x35從ascii碼表示的數(shù)字來看,1234 > 5, 但從字典序來看,1234 < 5

(2)具有相同前綴的ascii碼比較1234 -> 0x31 32 33 3412340 -> 0x31 32 33 34 00在C語言中,字符串一般是以0自己結(jié)尾的。本例的兩個字符串雖然前綴相同,但第二個末尾多了0字節(jié),則第二個“較大”。

(3)正數(shù)與負數(shù)的比較int類型的100 -> 0x00 00 00 64int類型的-100 -> 0xFF FF FF 9C100 > -100,但其二進制表達中,100 < -100

我們可以將這個比較規(guī)則總結(jié)如下:

從左到右逐個字節(jié)進行比較,以第一個不同字節(jié)的比較結(jié)果作為兩個byte[]的比較結(jié)果

字節(jié)的比較是按無符號數(shù)方式進行的

“不存在”比“存在”小

常見的rowkey編碼問題:

有符號數(shù):二進制表示中,有符號數(shù)的首bit是1,在字典序規(guī)則下,負數(shù)比正數(shù)大,所以,當(dāng)rowkey的值域同時包含正數(shù)和負數(shù)時,需要對符號位進行反轉(zhuǎn),以確保正數(shù)比負數(shù)大

倒序:通常用long來描述時間,一般都是倒排的,假設(shè)原始值是v,則v的倒序編碼是Long#MAX_VALUE - v。

下面通過一個前綴掃描的案例來體會一下這個比較規(guī)則的應(yīng)用。

示例:前綴掃描

Hbase的rowkey可以理解為單一主鍵列。如果業(yè)務(wù)場景需要多列一起構(gòu)成聯(lián)合主鍵(也叫多列主鍵,組合主鍵,復(fù)合主鍵等等),就需要將多列拼接為一列。一般來說,直接將二進制拼接在一起即可。例如:

rowkey組成:userId + ts

為了簡單,假設(shè)userid和ts都是定長的,且只有1個字節(jié)。例如:

HBase中數(shù)據(jù)分布模型是怎么樣的

現(xiàn)在,我們要做的事情是,查找某個userid = 2的所有數(shù)據(jù)。這是一個典型的前綴掃描場景,我們需要構(gòu)造一個Scan操作來完成:設(shè)置正確掃描范圍[startRow, stopRow),與region的邊界一樣,scan的范圍也是一個左閉右開區(qū)間。

一個直接的思路是找到最小和最大的ts,與userid = 2拼接,作為查詢范圍,即[0x02 00, 0x02 FF)。由于scan是左臂右開區(qū)間,則0x02 FF不會被作為結(jié)果返回。所以,這個方案不可行。

正確的scan范圍必須滿足:

startRow:必須必任何userId = 2的rowkey都小,且比任何userId = 1的rowkey都大

stopRow:必須必任何userId = 2的rowkey都大,且比任何userId = 3的rowkey都小

那如何利用rowkey的排序規(guī)則來“找到”這樣一個掃描范圍呢?

HBase中數(shù)據(jù)分布模型是怎么樣的  正確的掃描范圍是[0x02, 0x03)。

0x02比任何userid = 2的行都小。因為ts這一列是缺失的。同理,0x03比任何userid = 2的行都大,又比任何userId = 3的行都小??梢?,要實現(xiàn)前綴掃描,只根據(jù)前綴的值就可以得到所需的startRow和stopRow,而不需要知道后面的列及其含義。

請讀者仔細體會這個例子,然后思考下面幾個場景該如何構(gòu)造startRow和stopRow(答案見文末)。

where userid = 2 and ts >= 5 and ts < 20

where userid = 2 and ts > 5 and ts < 20

where userid = 2 and ts > 5 and ts <= 20

where userid > 2 and userid < 4

還有下面這些組合場景:

where userid in (3, 5, 7, 9)

where userid = 2 and ts in (10, 20, 30)

現(xiàn)在,已經(jīng)可以感受到使用scan的難點和痛點所在了。在上面的例子中,只有兩個定長的列,但在實際業(yè)務(wù)中,列可能是變長的,有各種各樣的數(shù)據(jù)類型,各種豐富的查詢模式。此時,構(gòu)造一個正確、高效的scan是有難度的。那為什么會有這些問題呢?有沒有系統(tǒng)性的解決方案呢?

從形式是看,這是一個“如何將業(yè)務(wù)查詢邏輯轉(zhuǎn)換為HBase的查詢邏輯”的問題,本質(zhì)上是關(guān)系表模型到KV模型的映射問題。HBase僅提供了KV層的API,使得用戶不得不自己實現(xiàn)這兩個模型之間的轉(zhuǎn)換。所以,才會有上面這么多的難點問題。不僅是HBase,所有的KV存儲系統(tǒng)在面臨復(fù)雜的業(yè)務(wù)模型時,都面臨相同的困境。

這個問題的解法是SQL on NoSQL,業(yè)界這類方案有很多(如Hive,presto等),HBase之上的方案就是Phoenix。此類方案通過引入SQL來解決NoSQL的易用性問題。對于傳統(tǒng)的關(guān)系型數(shù)據(jù)庫,雖然有強大的SQL和事務(wù)支持,但擴展性和性能受限,為了解決性能問題,MySQL提供了基于Memcached的KV訪問方式;為了解決擴展性問題,有了各種NewSQL的產(chǎn)品,如Spanner/F1,TiDB,CockroachDB等。NoSQL在做SQL,支持SQL的在做KV,我們可以想象一下未來的存儲、數(shù)據(jù)庫系統(tǒng)會是什么樣子。這個話題很大,不在本文的討論范圍內(nèi),這里就不展開了。

region的元數(shù)據(jù)管理與路由

前面我們討論了將一張表的行通過合理的region劃分,可以得到數(shù)據(jù)量大致接近的region分布。通過合理的運維手段(region的分裂與合并),我們可以通保證在系統(tǒng)持續(xù)運行期間的region分布均勻。此時,數(shù)據(jù)在邏輯上的拆分已經(jīng)可以實現(xiàn)均勻。本節(jié)中我們看一下region如何分布在RS上,以及客戶端如何定位region。

因為region的rowkey范圍本身的不確定性或者主觀性(人為拆分),無法通過一個數(shù)學(xué)公式來計算rowkey屬于哪個region(對比一致性hash的分片方式)。因此,基于范圍進行的分片方式,需要一個元數(shù)據(jù)表來記錄一個表被劃分為哪些region,每個region的起止rowkey是什么。這個元數(shù)據(jù)表就是meta表,在HBase1.x版本中表名是“hbase:meta”(在094或更老的版本中,是-ROOT-和.META.兩個元數(shù)據(jù)表)。

我們從Put操作來簡要的了解region的定位過程。

ZK上找meta表所在的RS(緩存)

到meta表上找rowkey所在的region及這個region所在的RS(緩存)

發(fā)Put請求給這個RS,RS根據(jù)region名字來執(zhí)行寫操作

如果RS發(fā)現(xiàn)這個region不在自己這里,拋異常,客戶端重新路由

無論讀還是寫,其定位region的邏輯都是如此。為了降低客戶端對meta表的訪問,客戶端會緩存region location信息,當(dāng)且僅當(dāng)緩存不正確時,才需要訪問meta表來獲取最新的信息。所以,HBase的請求路由是一種基于路由表的解決方案。相對應(yīng)的,基于一致性Hash的分片方式,則是通過計算來得到分布信息的。

這種基于路由表的方式

優(yōu)點:region的歸屬RS可以任意更換,或者說,region在RS上的調(diào)度是靈活的、可人工干預(yù)的。

缺點:meta表是一個單點,其有限的吞吐限制了集群的規(guī)模和客戶端數(shù)量

region的靈活調(diào)度,結(jié)合存儲計算分離的架構(gòu),賦予了HBase極其強大的能力。

秒級擴容:新加入的RS只需要移動region即可立即投產(chǎn),不依賴數(shù)據(jù)的遷移(后續(xù)慢慢遷)

人工隔離:對于有問題的region(如熱點,有異常請求),可以手工移動到一臺單獨的RS上,進行故障域的快速隔離。

這兩點,是眾多基于一致性hash的分片方案無法做到的。當(dāng)然,為了獲得這種靈活性,HBase所付出的代價就是復(fù)雜的meta表管理機制。其中比較關(guān)鍵的問題就是meta表的單點問題。例如:大量的客戶端都會請求meta表來獲取region location,meta表的負載較高,會限制獲取location的整體吞吐,從而限制集群的規(guī)模和客戶端規(guī)模。

對于一個擁有數(shù)百臺機器,數(shù)十萬region的集群來說,這套機制可以很好的工作。但當(dāng)集群規(guī)模進一步擴展,觸及到meta表的訪問上限時,就會因meta表的訪問阻塞而影響服務(wù)。當(dāng)然,絕大多數(shù)的業(yè)務(wù)場景都是無法觸達這個臨界規(guī)模的。

meta表的問題可以有很多種解決思路,最簡單的方式就是副本。例如TiDB的PD服務(wù),獲取location的請求可以發(fā)送給任何一臺PD服務(wù)器。

region的調(diào)度

下面我們討論region調(diào)度問題:

region在RS之間的負載均衡

同一個region在多個RS上調(diào)度

對于第一個問題,HBase的默認均衡策略是:以表為單位,每個RS上調(diào)度盡可能相同數(shù)量的region。

這個策略假設(shè)各個region的數(shù)據(jù)量分布相對均勻,每個region的請求相對均勻。此時,該策略非常有效。這也是目前使用最多的一種。同時,HBase也提供了基于負載的調(diào)度(StochasticLoadBalancer),會綜合考慮多種因素來進行調(diào)度決策,不過,暫時缺少生產(chǎn)環(huán)境使用的案例和數(shù)據(jù)。

對于第二個問題,region同一時間只在一臺RS上調(diào)度,使得HBase在請求成功的情況下提供了強一致的語義,即寫成功的數(shù)據(jù)可以立即被讀到。其代價是region的單點調(diào)度,即region所在的服務(wù)器因為各種原因產(chǎn)生抖動,都會影響這個region的服務(wù)質(zhì)量。我們可將影響region服務(wù)的問題分為兩類:

不可預(yù)期的:宕機恢復(fù),GC,網(wǎng)絡(luò)問題,磁盤抖動,硬件問題等等

可預(yù)期的(或人為的):擴容/縮容導(dǎo)致的region移動,region split/merge等。

這些事件發(fā)生時,會對這個region的服務(wù)或多或少產(chǎn)生一些影響。尤其在宕機場景,從ZK發(fā)現(xiàn)節(jié)點宕機到region的re-assign,split log,log replay,一些列步驟執(zhí)行完,一般都需要1分鐘以上的時間。對于宕機節(jié)點上的region,意味著這段時間這些region都無法服務(wù)。

解決方案依然是副本方案,讓region在多個RS上調(diào)度,客戶端選擇其中一個進行訪問,這個特性叫“region replia”。引入副本必然帶來額外的成本和一致性問題。目前這個特性的實現(xiàn)并未降低MTTR時間,內(nèi)存水位的控制、臟讀,使得這個特性仍未在生產(chǎn)中大規(guī)模使用。

以上是“HBase中數(shù)據(jù)分布模型是怎么樣的”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI