海量儲存系列之十二

2021-09-24 14:33:38 字數 3803 閱讀 3582

目前,團隊blog和sina輕部落格的發布進度已經完全相同,後續會全部

時間隔了比較久了,因為最近在過年臨近,所以都在準備這方面的事情。這裡提前祝大家新年快樂。

然後還是回到我們的正題兒吧:)

本章,我們主要來討論資料的管理和擴容中最重要的乙個部分,資料遷移。

資料遷移是資料運維中最為重要的乙個部分,在前面的文章中已經提到過,作為有狀態的資料節點,在網際網路行業的主要追求就是,無限的水平擴充套件能力,這種水平擴充套件,主要用於解決兩類問題,一類是磁碟空間不足的問題,一類是效能不足的問題。

為了達到這種能力,一般來說主要也就是這樣乙個思路,盡可能的讓資料不動,只通過規則變動的方式來完成擴容,如果這種方式無法滿足要求,那麼再通過移動資料的方式,來滿足其他的一些需求。

下面來進行下分析。

只通過變動規則的方式擴容,舉個最簡單的例子,就是一組按照時間或自增id的資料。那麼最簡單的切分方式,就是按照時間或id的範圍,將一組資料直接對映到某個具體的機器上,類似

if(gmt>=2010andgmt<2011)

returndatanode1;

elseif(gmt>=2011andgmt<2012)

returndatanode2;

elseif(gmt>=2012andgmt<20121223)

returndatanode3;

…使用這種方式的好處,顯而易見,就是不用動資料,方法簡單。

但帶來的壞處也明顯,就是不移動資料,那麼如果一組資料已經成為熱點,那麼永遠也沒有機會將熱點資料分開到不同的機器裡用以減輕熱點的損耗了。而,這種情況是非常有可能的,對於一對多的模型,如果按照一去儲存資料,那麼因為多的資料量的不斷擴充套件,會最終導致單個機器的資料量和io超限。

為了解決上述矛盾,就需要引入資料的遷移的方法了,簡單來說,就是按照規則將資料從原來的一組機器上,遷移到新的一組機器上去,這樣規則和資料一起變動,就可以有效的解決上面所說的熱點問題,盡可能讓所有的機器均勻的發揮效用。

思路很簡單,但工程實踐就複雜多了,下面來描述幾種擴容的模式,希望大家能針對這幾種場景以及我的分析,對如何解決這個問題有個更深入的認識。

所有有狀態的資料,其實都需要有擴容的策略,在這些擴容的模式中,最簡單的莫過於對cache節點的擴容了。因為cache本身其實只是乙個一致的資料的乙個快照,快照的意義就在於:如果你對快照的資料是否正確有異議,可以直接去從資料的源頭再查一次寫回快照中,即可保證資料的最新。

那麼對於快取資料,一般來說快取的更新邏輯有兩種,一種是寫的時候同步更新快取。一種是先讀快取,快取沒有的時候讀資料庫讀出最新值後更新快取,一般來說是兩種快取模式組合使用,因為沒有***。對於這種情況的快取節點擴容,最簡單的做法是,只需要直接改變規則即可。

如,假設原來的資料是按照id%4進行切分的,那麼如果規則換為id%8.那麼有一半的資料就無法被訪問到。但沒關係,因為業務的實際邏輯是,如果讀不到,就讀穿快取去資料庫裡面取資料再更新回快取,所以很快,資料會按照新的id%8進行填充,擴容就完成了。

當然,實際的擴容比這個要複雜一點,因為,要考慮規則變動後,讀穿的次數增多,導致資料庫壓力上公升的問題,所以要盡可能的避免過多的資料讀穿快取,這時候會使用我們在以前的文章中討論過的一致性hash或虛擬節點hash,使用緩慢更新對映關係的方式,來降低擴容對資料庫帶來的壓力。

以上是最簡單的規則和資料一起移動的例子,從上述例子可以分析出,其實規則遷移的最主要問題在於如何保證規則變更時,資料能夠在規則發生變動的時候對外部保證資料是最新的讀取,在快取擴容的case中,這個資料保證最新的任務,是由資料庫這個元件來完成的。所以快取擴容是相對最為簡單的。

那麼,自然的就會產生另外乙個疑問:對於資料庫,怎麼保證這個一致性的讀取呢?這也是我們這一章要闡明的最重要的問題。

資料的一致性讀,一般來說就只有兩種做法。第一種是共享記憶體指標,說白了就是資料只有乙份,但指向該資料的指標可能是多個。還有一種就是資料複製,資料的複製,保證一致性的難度會很大。更多的情況是按照實際的需求,取兩種模式的折衷。

對資料節點的擴容而言,其實核心就是資料的複製,既然複製,那麼一致性就非常難以保證,於是我們也就只能盡可能巧妙地利用手頭的工具,取折衷,用以盡可能的減少不一致的影響。

為了解決這個一致性的問題,我們需要在規則上引入版本,這個概念,主要是用於規定什麼時候資料應該以什麼規則進行訪問。這樣,就可以避免資料複製過程中所帶來的不一致的問題了。

假設,我們原來的規則,版本號為0,新的規則,版本號為1.那麼,開始的時候,客戶端所持有的資料的切分規則是版本0,所有資料在老的一組機器上進行讀取和寫入,不會出現問題。當我給定v0和v1兩個版本同時存在時,從客戶端就可以意識到,目前的規則是兩份並存,資料可能是不一致的,這時候最簡單的處理策略是,阻止一切讀取和寫入,這樣資料的不一致就不會發生了(哈哈,因為本身不允許讀寫了嘛。。),而當規則變為只有v1的時候,那麼客戶端就可以知道,目前只有乙個規則了,按照這個規則,進行資料訪問就可以了。

使用版本號,就可以讓客戶端能夠有機會意識到資料在某個時間段可能存在著不一致,應該加以針對性的處理,這樣就可以規避資料讀寫的不一致的問題了。

解決了不一致的問題,***接著要解決的問題有兩個:

我如何知道應該讓哪些資料移動到哪台機器上?

我如何盡可能的減小規則並存時的停寫的資料範圍?

針對這個問題,外面開源的社群,最常用的解決方法是一致性hash。

在一致性hash中,在某個地方加一組機器,可以很容易的**應該將哪個節點的資料移動到新的節點上。同時,又可以**,哪些節點不會受到影響,哪些不受到影響的節點,完全可以開放讀取,而受到影響的節點,則阻止訪問即可。

如上圖中,

node4和node2中間,加了乙個node5,那麼很容易的可以知道,只需要將node4中的一部分資料,寫入新的node5即可。而node2,node1,node3的資料不受到影響,可以繼續允許訪問。

這樣就可以比較成功的解決上面提到的兩個問題了。

但從這篇文章的討論中,我們也很容易可以看到,一致性hash也有他自己的問題。

於是,自然就有人要問,有沒有其他的做法呢?

自然是有啦,下面來介紹一下**tddl在這方面的工程實踐吧。以下是純粹乾貨,目前暫時沒見過業內使用類似方式,這種模式在**也經歷了較多次的自動擴容考驗,能夠滿足我們的需求,相信也一定能滿足您的需求,因為它什麼都沒做,也什麼都做了:).

首先是需求描述:分析**的需求,簡單概括就是一句話,業務方的規則需求,複雜到無以復加,絕非簡單一致性hash或簡單btree可以滿足,為了不同的業務需求,會有種類很多的切分規則。

需求分析:

需求分析其實就是挖掘需求的含義,找到哪些是真實的需求,哪些不是,將不是的砍掉,看看剩下的能不能滿足的過程:)

擴容系統的技術特點:

規則系統要自定義,因為這是業務核心,只有業務知道他們的資料怎麼分配會獲得比較均勻的訪問模型。

擴容「不是」常態,一般來說擴容的週期是3個月~6個月,甚至更長。如果乙個業務,每6天要擴容一次,那採購人員絕對會抄傢伙找他們team幹架去了

擴容本身不是不能做,但難度較大,一般來說需要幾個人一起參與,最少有資料運維人員,系統運維人員以及開發人員參與,一幫苦13程式設計師夜裡3點多鬧鐘叫起來,睡眼朦朧的進行機械的操作。難度可想而知。

基於這些技術特點,可以作如下分析

業務的變化要求資料擴容的規則要盡可能的自定義,可以有些預先定義好的規則模型,但不能強制要求業務必須走定義好的模型。

自動擴容,意義不大,如果只是讓業務人員根據資料點個確定,是最容易被接受的擴容模式

要盡可能的避免擴容本身對業務本身帶來的影響,同時要盡可能減輕開發人員的熬夜次數。

所以我們設計了如下的系統,他滿足以下特性

規則完全自定義,你可以隨便寫任何的ifelse等指令碼**。

只對擴容需求提供決策支援和方案生成,但決策由人進行。

除了決策

海量儲存系列之十三

在上一章中,我們主要介紹了規則引擎中最重要的乙個部分,自動擴容,在今天的章節,我們主要還是介紹一下我們在 tddl中的工程實踐吧。首先從原理開始吧。規則引擎是什麼呢?對應在上述例子裡面,其實就是dbnum pk 3 這個規則。他的變化可能很多,比如對於一致性hash則變為乙個if else 的表示式...

海量儲存系列之六

上次我們講到,單機事務個我們面臨的問題,下面我們來說一些我所知的解決的方法。在我開始做 資料層的時候,被問得最多的無非也就是 如何做事務,如何做join.至今仍然如此,我一般都會簡單而明確的跟對方說 沒有高效的實現方法。雖然沒有高效的實現,但實現還是有的。作為引子,我們先來介紹一下這種實現的方式。我...

海量儲存系列之五

在上一章節,我們一起瀏覽了如何進行單機事務操作。下面我們來看一下分布式場景中我們碰到的問題吧。需要說明的一點是,這裡涉及到的權衡點非常的多。就我短短的工作經驗裡面,也只是能夠簡單的涉獵一部分,因為在事務這個領域,目前大家都在嘗試提出各種各樣的不同的方法,而在taobao,我們目前也沒有完美的解決這個...