怎樣實踐微信后臺的海量數(shù)據(jù)冷熱分級架構(gòu)設(shè)計

今天就跟大家聊聊有關(guān)怎樣實踐微信后臺的海量數(shù)據(jù)冷熱分級架構(gòu)設(shè)計,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

創(chuàng)新互聯(lián)專注于西崗企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站,成都商城網(wǎng)站開發(fā)。西崗網(wǎng)站建設(shè)公司,為西崗等地區(qū)提供建站服務(wù)。全流程按需制作,專業(yè)設(shè)計,全程項目跟蹤,創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)

微信的后臺數(shù)據(jù)存儲隨著微信產(chǎn)品特性的演進(jìn),經(jīng)歷了數(shù)次的架構(gòu)改造,才形成如今成熟的大規(guī)模分布式存儲系統(tǒng),有條不紊的管理著由數(shù)千臺異構(gòu)機(jī)型組成的機(jī)器集群,得以支撐每天千萬億級的訪問、鍵值以及 PB 級的數(shù)據(jù)。

作為以手機(jī)為平臺的移動社交應(yīng)用,微信內(nèi)大部分業(yè)務(wù)生成的數(shù)據(jù)是有共性可言的:數(shù)據(jù)鍵值帶有時間戳信息,并且單用戶數(shù)據(jù)隨著時間在不斷的生成。我們將這類數(shù)據(jù)稱為基于時間序的數(shù)據(jù)。比如朋友圈中的發(fā)表,或者移動支付的賬單流水等業(yè)務(wù)生成的數(shù)據(jù)都滿足這樣的特征?;跁r間序的數(shù)據(jù)都天然帶有冷熱分明屬性――這是由手機(jī)的物理特性決定的,它的尺寸有限的屏幕所展示的數(shù)據(jù)只能分屏,通過手指的滑動,平滑而又連續(xù)的沿時間軸依次訪問――通常是由最新生成的數(shù)據(jù),慢慢回溯到較早前的數(shù)據(jù)。同時朋友圈等業(yè)務(wù)都是信息讀擴(kuò)散的應(yīng)用場景,這就意味著它們生成的后臺數(shù)據(jù)具有讀多寫少的鮮明特征。

在微信的實際應(yīng)用場景中,這類數(shù)據(jù)的主要特點包括:數(shù)據(jù)量大、訪問量大、重要程度高等。這些特點在現(xiàn)網(wǎng)的實際運營過程中,給我們帶來了非常大的挑戰(zhàn),主要包括:

  1. 數(shù)據(jù)量大,需求的存儲容量高――基于時間序的數(shù)據(jù)通常不會刪除,而是隨著時間不斷積累,數(shù)據(jù)量達(dá)到 PB 級別,相應(yīng)需要的存儲空間也與日俱增;

  2. 訪問量大,節(jié)日效應(yīng)明顯――基于時間序的數(shù)據(jù)往往是熱點業(yè)務(wù)生成的數(shù)據(jù),它們的訪問量居高不下,基本維持在每分鐘數(shù)十億次的級別。尤其是在節(jié)日期間,瞬發(fā)訪問量更可達(dá)平日的三至五倍;

  3. 重要性高,用戶感知明顯,數(shù)據(jù)一旦丟失,導(dǎo)致用戶不能正常使用產(chǎn)品,并因此而轉(zhuǎn)化成的投訴率高。

通過堆機(jī)器來橫向擴(kuò)展存儲自然可以應(yīng)對如上的各種挑戰(zhàn),然而在成本預(yù)算緊張的前提下,機(jī)器數(shù)目是有限的。在這種情況下,基于時間序的海量數(shù)據(jù)的冷熱分級架構(gòu)便應(yīng)運而生。該架構(gòu)正是為了應(yīng)對后臺日益膨脹的這類數(shù)據(jù),本著充分利用機(jī)器資源,發(fā)揮各種硬件介質(zhì)特長的原則,結(jié)合數(shù)據(jù)的冷熱分明、讀多寫少的訪問特征而開發(fā)和設(shè)計出來的。它基于數(shù)據(jù)分層的理念,根據(jù)不同時間段的數(shù)據(jù)在訪問熱度和數(shù)據(jù)量上的差異,定制不同的服務(wù)策略,在縱向上擴(kuò)展存儲的邊界。橫向擴(kuò)展存儲是易于理解的,通過向原集群中增加相同類型的機(jī)器――其中必然涉及到一輪歷史數(shù)據(jù)的遷移――最終新舊機(jī)器負(fù)載均衡,彼此之間并無差異的對外提供服務(wù)。在這種方案下,數(shù)據(jù)橫向流動,系統(tǒng)一視同仁的對待,顯然并無因地制宜思想的容身之所。而縱向擴(kuò)展存儲的架構(gòu)便提供了這樣一種思路:

對熱點數(shù)據(jù),數(shù)據(jù)量少,但承擔(dān)的訪問流量大,我們當(dāng)然是希望它們能常駐內(nèi)存,因此系統(tǒng)提供了有強(qiáng)一致保證的內(nèi)存層,在應(yīng)對突發(fā)流量時,也可在不涉及歷史數(shù)據(jù)遷移的前提下,單獨、動態(tài)的快速擴(kuò)展內(nèi)存層。

對歷史數(shù)據(jù),數(shù)據(jù)存量大,但承擔(dān)的訪問量非常有限,我們當(dāng)然是不希望用昂貴的固態(tài)硬盤來存儲它們,因此,系統(tǒng)提供了廉價的機(jī)械盤層,并且有一套透明的冷數(shù)據(jù)剝離和批量下沉的流程,將存儲層中歷史數(shù)據(jù)源源不斷的抽離到機(jī)械盤層。

通過這樣的一種縱向分層、單獨擴(kuò)展的思路,即為我們系統(tǒng)提供了極大的靈活性,解決了節(jié)日期間存儲層面臨的內(nèi)存瓶頸,以從長遠(yuǎn)的角度為我們緩解了成本壓力,解決了存儲層面臨的磁盤容量瓶頸。

當(dāng)然一套成功的大型分布式系統(tǒng)僅有這些是不夠的,還必須包括數(shù)據(jù)多副本復(fù)制策略以及分區(qū)算法等,也要有能應(yīng)對復(fù)雜的現(xiàn)網(wǎng)運營環(huán)境的能力。我們結(jié)合各層的服務(wù)特點,制訂了相對應(yīng)的數(shù)據(jù)強(qiáng)一致算法,如內(nèi)存層通過版本號控制來保證與存儲層的完全一致,存儲層通過 Paxos Group 實現(xiàn)多副本容災(zāi),而機(jī)械盤層則通過串行寫來保證。我們同時也實現(xiàn)了自己的去中心化的數(shù)據(jù)路由算法,確保了數(shù)據(jù)和流量的均勻分布,并且保證這種特性在橫向擴(kuò)展后依然成立。

通過如上工作的努力,環(huán)環(huán)相扣,我們的基于時間序的海量數(shù)據(jù)的冷熱分層架構(gòu)成功的應(yīng)對了 PB 級數(shù)據(jù)、千億級訪問以及萬億級鍵值帶來的挑戰(zhàn)。

系統(tǒng)設(shè)計

數(shù)據(jù)模型

本文提及的海量數(shù)據(jù)的冷熱分級架構(gòu)是專門服務(wù)于基于時間序的數(shù)據(jù),它們主要特征為:

a). 數(shù)據(jù)鍵值帶有時間戳信息 ;

b). 單用戶數(shù)據(jù)隨著時間在不斷的生成。

我們設(shè)計的架構(gòu)強(qiáng)依賴于特性 a),各個環(huán)節(jié)基本上是依賴于鍵值中的時間戳來分發(fā)數(shù)據(jù)或者進(jìn)行數(shù)據(jù)排序的。至于鍵值中的時間戳如何生成、全局是否維持統(tǒng)一時間、如何維持等則不在本文的討論范圍,通常這由前端的業(yè)務(wù)特性以及后臺的時間服務(wù)器策略決定的。

而特性 b) 則保證了本架構(gòu)的必要性、實用性。如果數(shù)據(jù)規(guī)模有限,以用戶的賬戶信息舉例,它就像我們?nèi)粘I钪械膽艨诒?,它只有一份,對單用戶而言不會新增。則我們通常用固定的機(jī)器集群存儲就可以,并且鮮有變更。而我們要處理的是用戶的日記本、或者記賬簿,它們每天都在不斷生成新數(shù)據(jù)。

我們以現(xiàn)網(wǎng)某個集群的實例情況舉例,說明下此類業(yè)務(wù)數(shù)據(jù)有如下的特點:

1.、數(shù)據(jù)量大,PB 級數(shù)據(jù),萬億級鍵值,并且在源源不斷的生成中,然而新生成的數(shù)據(jù)相較于歷史存量數(shù)據(jù)占比小。下圖展示了該集群數(shù)據(jù)在各時間段的一個占比情況。

怎樣實踐微信后臺的海量數(shù)據(jù)冷熱分級架構(gòu)設(shè)計

2、訪問量大,峰值可達(dá)每分鐘數(shù)十億次訪問,尤其是在節(jié)日期間,用戶高漲的熱情更可以轉(zhuǎn)化成平日三至五倍的訪問量。同時具有冷熱分明、讀多寫少 (讀寫比例甚至可達(dá) 100:1) 的訪問特征,比如節(jié)日期間倍增的訪問通常是對節(jié)日期間生成的新增數(shù)據(jù)的訪問。下圖展示了該集群訪問在各時間段的一個占比情況。

怎樣實踐微信后臺的海量數(shù)據(jù)冷熱分級架構(gòu)設(shè)計

3、數(shù)據(jù)安全性要求高,這類數(shù)據(jù)通常是用戶感知敏感數(shù)據(jù),一旦丟失,轉(zhuǎn)化成的用戶投訴率高。

系統(tǒng)架構(gòu)

系統(tǒng)由三個層次組成,如圖所求,分別是內(nèi)存層、存儲層(熱數(shù)據(jù)存儲層)以及機(jī)械磁盤層(冷數(shù)據(jù)存儲層)。從時間軸上看,它們服務(wù)的數(shù)據(jù)由熱至冷。如下圖所示:

怎樣實踐微信后臺的海量數(shù)據(jù)冷熱分級架構(gòu)設(shè)計

從客戶端的角度看,三層都是并列的,客戶端都會直接的與某層中的某臺機(jī)器發(fā)生通信。具體的區(qū)別點在于,內(nèi)存層和機(jī)械磁盤層對客戶端而言是只讀的。所有的寫都是由客戶端直接寫向存儲層。我們將去中心化的配置分發(fā)到客戶端機(jī)器上,配置的類型包括內(nèi)存層路由、存儲層路由以及其它元數(shù)據(jù),客戶端根據(jù)配置中的時間分隔點以及流量比例,來決定將當(dāng)前的讀請求分發(fā)到內(nèi)存層還是存儲層的具體機(jī)器上。配置支持快速分發(fā)和動態(tài)加載,可以在秒級實現(xiàn)更新。

機(jī)械磁盤層的路由對客戶端而言是透明的,存儲層保存了下沉到機(jī)械磁盤層的數(shù)據(jù)鏈接,鏈接包含了文件編號、內(nèi)部偏移和大小,而客戶端對此是不知情的。當(dāng)已下沉數(shù)據(jù)的讀請求分發(fā)到存儲層機(jī)器上時,存儲層會計算出該數(shù)據(jù)各副本在冷數(shù)據(jù)存儲層對應(yīng)的機(jī)器地址,然后將它和文件鏈接一起回復(fù)給客戶端??蛻舳嗽侔凑针S機(jī)的策略在多副本之間選擇一份讀取,從這個角度看,冷數(shù)據(jù)存儲層對客戶端而言更像個遠(yuǎn)程文件系統(tǒng),而 inode 信息和路由表是放在熱數(shù)據(jù)存儲層的。

下面我們再詳細(xì)的分析各層的設(shè)計策略。

內(nèi)存層

內(nèi)存層從表現(xiàn)上更像是一個緩存代理,然而普通的緩存在處理數(shù)據(jù)有效性上是乏力的。常見的策略如寫時淘汰,每次寫存儲層之前,都先清理掉緩存中相應(yīng)的數(shù)據(jù),確保失效。然而數(shù)據(jù)在緩存中通常也是多副本的,這個方案即無法處理網(wǎng)絡(luò)分區(qū)錯誤,并且寫時淘汰也會產(chǎn)生多次 RPC 請求,過份的消耗系統(tǒng)資源。另外一種常見策略是有限的數(shù)據(jù)一致性,即過時淘汰的策略。在將數(shù)據(jù)寫入緩存時,會附帶一個有效時間,在這個有效期內(nèi),該數(shù)據(jù)一直被認(rèn)為是正確的,并不關(guān)心真實情況是如何的。這種緩存只能應(yīng)用于對數(shù)據(jù)實時性要求不高的服務(wù)。對微信的敏感業(yè)務(wù)而言,我們更需要能保證數(shù)據(jù)強(qiáng)一致的分布式緩存。

我們通過版本號來實現(xiàn)了這一目的。我們?yōu)榫彺嬷械拿恳环輸?shù)據(jù)都維持了一份版本號,存儲層中相應(yīng)的也有一份。只有當(dāng)緩存中的版本號與存儲層的版本號達(dá)到一致時,才會認(rèn)為緩存中的數(shù)據(jù)是有效的。所以,客戶端每次對內(nèi)存層的讀請求,都會由緩存層相應(yīng)的產(chǎn)生一次讀請求發(fā)到存儲層。在一次 RPC 請求中完成有效性的識別以及過期數(shù)據(jù)的更新。

怎樣實踐微信后臺的海量數(shù)據(jù)冷熱分級架構(gòu)設(shè)計

從直覺上看,采用這種方案的強(qiáng)一致緩存并沒有降低存儲層的訪問壓力。因為客戶端對緩存層的請求,與緩存層對存儲層的請求是 1:1 的。然而這個方案點的關(guān)鍵在于,我們成功的疏解了存儲層的內(nèi)存瓶頸。將存儲層緩存數(shù)據(jù)的功能,轉(zhuǎn)移到緩存層的內(nèi)存上。我們現(xiàn)在對存儲層的要求就是能夠盡量的緩存更多的版本號,提供高效的版本號訪問能力就可以了。從這種意義上來看,這個強(qiáng)一致性緩存就是存儲層內(nèi)存的延伸。因此,我們將它稱為內(nèi)存層。它的優(yōu)勢在于可動態(tài)的調(diào)整流量比例,并且可以在訪問高峰期快速的擴(kuò)容。后面的章節(jié)我們也描述了如何通過工程手段優(yōu)化版本號交互帶來的資源消耗。

為了系統(tǒng)的健壯性,一些異常情況也是需要考慮的,如果一臺內(nèi)存層機(jī)器突然離線,會有數(shù)十 G 的緩存數(shù)據(jù)失效,我們當(dāng)然不會希望這數(shù)十 G 數(shù)據(jù)的壓力,會全部的落到一臺存儲機(jī)器的磁盤上。――這無疑會引起系統(tǒng)的抖動。因此,我們按照組的方式來部署了內(nèi)存層。每組有多臺機(jī)器。一份數(shù)據(jù)可能在這多臺機(jī)器內(nèi)有多個副本??蛻舳送ㄟ^隨機(jī)的次序訪問這些機(jī)器。這樣就盡力避免了單結(jié)點失效對整個系統(tǒng)的影響。

我們在內(nèi)存層中設(shè)計了簡單、輕量的支持變長數(shù)據(jù)的緩存結(jié)構(gòu)。每臺機(jī)器包含數(shù)十條 LRU 鏈,每條鏈都是一個共享內(nèi)存形式的一維數(shù)組。所有的數(shù)據(jù)都追加寫在數(shù)組的最新位置,到尾部后就從頭開始循環(huán)。自然,這樣的結(jié)構(gòu)需要一個索引來記錄數(shù)據(jù)的位置。這種方式固然浪費一些內(nèi)存空間,但避免了內(nèi)存的動態(tài)分配。

存儲層

存儲層在整個系統(tǒng)架構(gòu)中處于核心的位置。內(nèi)存層和機(jī)器硬盤層都依賴于它的實現(xiàn)。前文提及,提供高效輕量的版本號訪問能力是強(qiáng)一致內(nèi)存層實現(xiàn)的關(guān)鍵。同時,源源不斷的將冷數(shù)據(jù)下沉到機(jī)械硬盤層的需求,就暗示了在存儲層必須有這樣一種特性:冷數(shù)據(jù)是易于從所有數(shù)據(jù)中剝離,并且收集的。――這樣就意味著,如果在存儲層中數(shù)據(jù)是平坦的,冷熱數(shù)據(jù)混雜在一起,那么我們在抽離冷數(shù)據(jù)的時候,就要把硬盤中所有的數(shù)據(jù)遍歷一輪,無疑會消耗比較多的系統(tǒng)資源。

因此我們采用了 lsm-tree 算法來實現(xiàn)這一需求。該算法和 B+ 樹一樣是種建立索引的技術(shù)。不同的是它基于多組件 (C0\C1 等組件),通過延遲提交和歸并排序的方式,將 B+ 樹的隨機(jī) IO 轉(zhuǎn)變成了內(nèi)存操作和順序 IO。在我們的訪問模型下,所有的寫都是熱點數(shù)據(jù),只會提交到 C0 組件。然后在適當(dāng)?shù)臅r機(jī),同 C1 組件中的數(shù)據(jù)進(jìn)行多路歸并排序。通過該算法,我們可以同時實現(xiàn)數(shù)據(jù)分層和數(shù)據(jù)有序的目的。

怎樣實踐微信后臺的海量數(shù)據(jù)冷熱分級架構(gòu)設(shè)計

Leveldb 是 Google 公司開源的存儲引擎庫,它正是基于 lsm-tree 算法的思想開發(fā)出來的。因此,我們復(fù)用了它成熟的數(shù)據(jù)結(jié)構(gòu)組件,如日志格式、數(shù)據(jù)文件格式、內(nèi)存表格式等。然而它其中的一些運行時策略,卻會給我們的現(xiàn)網(wǎng)運營帶來麻煩。比如說運行時不受限的 compact 策略、數(shù)據(jù)文件索引的懶加載等,會觸發(fā)不可控的讀盤,造成服務(wù)的抖動;同時大量的動態(tài)內(nèi)存分配也會對機(jī)器的內(nèi)存使用帶來一定不可控的因素。因此,我們拋棄了這些運行時行為,定義了自己的管理策略,使系統(tǒng)變得更加可控。同時,我們利用不同數(shù)據(jù)的訪問差異,對冷、熱數(shù)據(jù)的存儲進(jìn)行了各自的定制,按照時間段定義按塊壓縮的粒度、索引的粒度等,行之有效的調(diào)和了 CPU、內(nèi)存、磁盤容量、磁盤 IO 等系統(tǒng)資源之間的轉(zhuǎn)換關(guān)系。

冷數(shù)據(jù)的鏈接和冷集群的路由表,都是記錄在存儲層中而對前端不可見的。具體的設(shè)計思想,我們在下節(jié)中詳述。

機(jī)械硬盤層

機(jī)械硬盤容量雖大,但是 IO 性能低下,故障率高。一種常見的思路是冷數(shù)據(jù)存儲層獨立與熱數(shù)據(jù)存儲層,而對客戶端直接可見――客戶端持有一份冷數(shù)據(jù)存儲層的路由,并且獨自路由――這無疑是種簡單、易于理解的方案,但是在我們的應(yīng)用場景中面臨著兩個問題:無法精確防空以及加劇機(jī)械硬盤層的 IO 緊張。

定義 TB 訪問量為每 TB 數(shù)據(jù)的每秒的訪問次數(shù)。在我們的應(yīng)用場景中,每 TB 歷史數(shù)據(jù)的實際訪問量設(shè)為 N,則機(jī)械硬盤的服務(wù)能力僅為 N 的一半。如果冷數(shù)據(jù)存儲層獨立,則它需要自己維持所有的數(shù)據(jù)索引,而內(nèi)存容量不足以支持?jǐn)?shù)十 T 數(shù)據(jù)的索引,只能將索引落盤,則每次對數(shù)據(jù)的讀取都要帶來兩次隨機(jī)讀盤。因此,我們將冷數(shù)據(jù)索引以及冷數(shù)據(jù)存儲層的路由表,都放到了熱數(shù)據(jù)存儲層中,而對前端不可見。

為了容災(zāi),我們必須為每份數(shù)據(jù)存儲多份副本。如果采用雙副本方案,則系統(tǒng)需要冗余 50% 的訪問能力,以應(yīng)對另外一份副本失效的情況,在 io 瓶頸的前提下,這種方案是不可取的。因此我們采用了三副本方案,只要冗余三分之一的能力。每份副本分布在不同的園區(qū),可以實現(xiàn)園區(qū)級的容災(zāi)。

怎樣實踐微信后臺的海量數(shù)據(jù)冷熱分級架構(gòu)設(shè)計

由于機(jī)械盤容量大、計算能力差,我們采用 NO RAID 的方式組織了盤組。為了更好的實現(xiàn)單盤失效導(dǎo)致數(shù)據(jù)丟失的故障的災(zāi)后恢復(fù),我們實現(xiàn)了同組三臺機(jī)器在盤級別數(shù)據(jù)的完全相同。為了達(dá)到盤級別的負(fù)載均衡,我們通過預(yù)計算路由、硬編碼的方式,實現(xiàn)了 (數(shù)據(jù) ->機(jī)器 ->盤 ->文件) 的單調(diào)映射,由數(shù)據(jù)的鍵值可以直接定位到盤的索引以及文件的編號。

怎樣實踐微信后臺的海量數(shù)據(jù)冷熱分級架構(gòu)設(shè)計

作為機(jī)械硬盤層的補(bǔ)充,一個冷數(shù)據(jù)下沉的模塊是必須的,它作為冷數(shù)據(jù)存儲層的唯一 Writer,我們通過兩階段提交的方式確保了下沉過程的透明性,通過控制流程發(fā)起時機(jī)保證資源使用不影響現(xiàn)網(wǎng)服務(wù),通過預(yù)占位、串行寫入的方式,確保了數(shù)據(jù)在冷數(shù)據(jù)存儲層文件級別的完全一致。

數(shù)據(jù)強(qiáng)一致性保證

業(yè)務(wù)要求系統(tǒng)必須保證在數(shù)據(jù)的多份副本之間保持強(qiáng)一致性。――這是一個歷久彌新的挑戰(zhàn)。我們將分內(nèi)存層、存儲層、機(jī)械硬盤層分別來考慮數(shù)據(jù)的強(qiáng)一致性維持。

強(qiáng)一致緩存

正如前文描述,內(nèi)存層作為一種強(qiáng)一致性分布式緩存,它完全是向存儲層對齊的,自身無法判別數(shù)據(jù)有效性,本身多副本之間也沒有交互的必要。它對前端而言是只讀的,所有的寫請求并不通過它,它只能算是存儲層中數(shù)據(jù)的一個視圖。所以它對前端數(shù)據(jù)有效性的承諾完全是依賴于存儲層的正確性的。

Paxos Group

我們基于 Paxos Group 實現(xiàn)了存儲層的數(shù)據(jù)一致性,通過采用無租約的方式,使得系統(tǒng)在保證強(qiáng)一致性的前提下達(dá)到了最大的可用性。Paxos 算法是由 Lesile Lamport 在論文中首提的,它唯一的作用是在多個參與者之間唯一的確定一個常量值。――這點同分布式存儲沒有直接關(guān)聯(lián)的。我們在 Paxos 算法的基礎(chǔ)上,設(shè)計出基于消息驅(qū)動的 Paxos Log 組件――每一條操作日志都要 Paxos 算法來確定,再進(jìn)一步實現(xiàn)了基于 Paxos Log 的強(qiáng)一致性讀寫。

Paxos Group 因為采用了無主模型,組內(nèi)所有機(jī)器在任一時刻都處于相同的地位。Paxos 算法本質(zhì)是個多副本同步寫算法,當(dāng)且僅當(dāng)系統(tǒng)中的多數(shù)派都接受相同值后,才會返回寫成功。因此任意單一節(jié)點的失效,都不會出現(xiàn)系統(tǒng)的不可用。

強(qiáng)一致性寫協(xié)議的主要問題來源于 Paxos 算法本身,因為要確保數(shù)據(jù)被系統(tǒng)內(nèi)的多數(shù)派接受,需要進(jìn)行多階段的交互。我們采用如下的方法,解決了 paxos 算法寫過程中出現(xiàn)的問題:基于 fast accept 協(xié)議優(yōu)化了寫算法,降低了寫盤量以及協(xié)議消息發(fā)送、接收次數(shù),最終實現(xiàn)了寫耗時和失敗的降低;基于隨機(jī)避讓、限制單次 Paxos 寫觸發(fā) Prepare 的次數(shù)等方法,解決了 Paxos 中的活鎖問題。

強(qiáng)一致性讀協(xié)議本身和 Paxos 算法并沒有太大的關(guān)系,只要確認(rèn)多副本之間的多數(shù)派,即可獲取到最新的數(shù)據(jù)。我們通過廣播的方式獲取到集群中多數(shù)機(jī)器(包含自身)的 paxos log 的狀態(tài),然后判斷本機(jī)數(shù)據(jù)的有效性。

當(dāng)系統(tǒng)中的單機(jī)節(jié)點失效,數(shù)據(jù)完全丟失的時候――這種情況是可以算是 Paxos 算法的盲區(qū),因為該算法基于所有的參與者都不會違背自己曾經(jīng)的承諾,即拜占庭失敗而導(dǎo)致的數(shù)據(jù)不一致。――而這種情況在現(xiàn)網(wǎng)運營中可謂是常態(tài),因此,我們引入了 Learner Only 模式。在該模式下故障機(jī)只接收已提交的數(shù)據(jù),而不參與 Paxos 協(xié)議的寫過程,意即不會因數(shù)據(jù)丟失而違背任何承諾。然后通過異步 catch up 和全量數(shù)據(jù)校驗快速從其它副本中恢復(fù)數(shù)據(jù)。

為了防止多節(jié)點同時失效,我們將數(shù)據(jù)的多副本分布在不同園區(qū)的機(jī)器上。園區(qū)是同一個城市不同數(shù)據(jù)中心的概念。如此,我們的結(jié)構(gòu)足以應(yīng)對單數(shù)據(jù)中心完全隔離級別的災(zāi)難。

串行寫入

因為對客戶端透明,冷數(shù)據(jù)下沉流程作為機(jī)械硬盤層的唯一寫者,則該層的數(shù)據(jù)一致性是易于實現(xiàn)的。我們通過三副本串行寫入、全部提交才算成功的方式來實現(xiàn)了多副本之間的數(shù)據(jù)一致性。

作為補(bǔ)充,冷數(shù)據(jù)集群為數(shù)據(jù)塊增加了 CRC 校驗和一致性恢復(fù)隊列,當(dāng)單機(jī)數(shù)據(jù)不可用 (丟失或者損壞) 時,首先客戶端會跳轉(zhuǎn)到其它備份中讀 (三機(jī)同時對外提供讀服務(wù)),一致性恢復(fù)隊列會異步的從其它備份數(shù)據(jù)塊中恢復(fù)本機(jī)數(shù)據(jù)。

因為采用了 No Raid 方式組織的盤組,并且同組機(jī)器間盤級別數(shù)據(jù)文件一致,在單盤故障引發(fā)數(shù)據(jù)丟失時,只要從其它機(jī)器相同序盤中傳輸數(shù)據(jù)文件即可。

數(shù)據(jù)分區(qū)

靜態(tài)映射表

數(shù)據(jù)分區(qū)的主要目的是為了確保同層機(jī)器間的負(fù)載均衡,并且當(dāng)機(jī)器規(guī)模發(fā)生變化后,在最終仍然可以達(dá)到負(fù)載均衡的一種狀態(tài)。

經(jīng)典的一致性哈希算法的初衷是為了健壯分布式緩存,基于運行時動態(tài)的計算哈希值和虛擬節(jié)點來進(jìn)行尋址。數(shù)據(jù)存儲與分布式緩存的不同在于,存儲必須保證數(shù)據(jù)映射的單調(diào)性,而緩存則無此要求,所以經(jīng)典的一致性哈希通常會使用機(jī)器 IP 等作為參數(shù)來進(jìn)行哈希,這樣造成的結(jié)果一方面是數(shù)據(jù)的落點時而發(fā)生改變,一方面是負(fù)載通常不均衡。因此我們改造了此算法。

我們通過預(yù)計算虛擬節(jié)點隨機(jī)數(shù)的方法,生成了割環(huán)點同實體機(jī)器之間的映射表。該映射表最多可支持一千組的集群規(guī)模,滿足在任意組數(shù)情況下,實體機(jī)器間割段長度維持差異在 2% 以內(nèi);并且增加任意組數(shù) (總組數(shù)上限不超過一千組),變動后的實體機(jī)器間的割段長度依然維持差異在 2% 以內(nèi)。我們將此映射表硬編碼,在運行時避免了計算的過程,數(shù)據(jù)根據(jù)鍵值哈希值尋址時,只要經(jīng)過一次二分查找即可獲取到對應(yīng)的實體機(jī)器的編號。我們在內(nèi)存層、存儲層以及機(jī)械硬盤層都采用了這個映射表,保證了數(shù)據(jù)在各層路由算法的一致。在工程實現(xiàn)方面,我們可以合理使用這個特性來批量合并請求,以降低資源消耗,這在稍后的章節(jié)會有詳細(xì)描述。

組內(nèi)均衡

組是數(shù)據(jù)分區(qū)的獨立單元,是虛擬節(jié)點對應(yīng)的實體單位。組之間是互相獨立的。每組由多臺物理機(jī)器組成,這是 Paxos Group 生效的基本單位。一份數(shù)據(jù)包括的多份副本分別散落在組內(nèi)的各臺機(jī)器上。為了在組內(nèi)機(jī)器上保證負(fù)載均衡,我們同樣設(shè)計了一套算法,規(guī)定了數(shù)據(jù)副本之間的訪問優(yōu)先級,前端會依優(yōu)先級逐一的請求數(shù)據(jù),只要成功獲取,即中斷這個過程。然后我們再將副本按優(yōu)先級均勻的散落在組內(nèi)機(jī)器上,如此即可實現(xiàn)組內(nèi)負(fù)載的均衡。

數(shù)據(jù)遷移

靜態(tài)映射表是非常靈活的,在不達(dá)到組數(shù)上限的情況下,可以任意的增加一組或者多組機(jī)器。當(dāng)然這個過程中一些數(shù)據(jù)的路由映射發(fā)生了改變,則就涉及到了歷史數(shù)據(jù)的挪騰。為了在挪騰的過程中不影響服務(wù),保證數(shù)據(jù)依然可讀可寫,我們開發(fā)出了對前端透明的,基于遷移標(biāo)志位,通過數(shù)據(jù)雙寫和異步挪數(shù)據(jù)的方式實現(xiàn)的安全的、可回退的數(shù)據(jù)遷移流程。

最小不變塊

存儲層和機(jī)械硬盤層通過冷數(shù)據(jù)鏈接耦合在了一起。因為兩層使用了相同的映射表,那么當(dāng)存儲層因擴(kuò)容而發(fā)生遷移時,那么冷數(shù)據(jù)鏈接無疑也要重新尋址,進(jìn)行一輪重新定位。如果我們以單鍵值為粒度記錄冷數(shù)據(jù)鏈接和進(jìn)行冷數(shù)據(jù)下沉,那么在萬億鍵值的語境下,效率無疑是低下。因此我們設(shè)計了最小不變塊的算法,通過兩階段哈希,使用中間的哈希桶聚集數(shù)據(jù),將數(shù)據(jù)鍵值和冷數(shù)據(jù)存儲層的機(jī)器路由隔離開來。通過該算法,我們可以實現(xiàn):批量的轉(zhuǎn)存冷數(shù)據(jù)、熱數(shù)據(jù)存儲層批量的以塊 (block) 為單位記錄冷數(shù)據(jù)鏈接、當(dāng)熱數(shù)據(jù)存儲層發(fā)生擴(kuò)容時,塊 (block) 內(nèi)的數(shù)據(jù)不因擴(kuò)容被打散掉,而可以整體的遷移到新目標(biāo)機(jī)上。

工程實現(xiàn)

糟糕的工程實現(xiàn)可以毀掉一個完美的系統(tǒng)設(shè)計,因此,如何在工程實現(xiàn)的過程中,通過技術(shù)的手段,提升系統(tǒng)的表現(xiàn),同樣值得重視。

高效緩存

內(nèi)存層的設(shè)計嚴(yán)重依賴存儲層數(shù)據(jù)版本號的高效獲取,那自然是版本號請求全落在內(nèi)存中就可以了。因此,針對這種情況我們?yōu)槎ㄩL的版本號設(shè)計了一套極簡的、輕量的、行之有效的緩存――內(nèi)存容量不足以支撐版本號全緩存。

怎樣實踐微信后臺的海量數(shù)據(jù)冷熱分級架構(gòu)設(shè)計

它的數(shù)據(jù)結(jié)構(gòu)只是一個二維數(shù)組,一維用來構(gòu)建 hash 鏈,一維用來實現(xiàn) LRU 鏈。每次讀或者寫都需要通過數(shù)組內(nèi)數(shù)據(jù)的挪動,來進(jìn)行更新。如此一來,我們就通過千萬級數(shù)目的 LRU 鏈群,實現(xiàn)了緩存整體的 LRU 淘汰。它具有定長,可共享內(nèi)存搭載,進(jìn)程重啟不丟失、內(nèi)存使用率高等優(yōu)點。

批量操作

對系統(tǒng)服務(wù)器而言,前端訪問過來的某個請求,其對應(yīng)的邏輯操作都是串行的,我們自然可以梳理這個串行流程中的 CPU 消耗點進(jìn)行優(yōu)化。然而當(dāng)主要的瓶頸被逐漸的消滅掉后,CPU 消耗點變得分散,優(yōu)化效果就變得微乎其微了。因此,我們只能尋找其它突破點。

我們發(fā)現(xiàn)在存儲引擎、一致性協(xié)議算法的實現(xiàn)流程中,邏輯操作步驟多,涉及到網(wǎng)絡(luò)交互,硬盤讀寫等過程。因此,我們決定合并不同請求中的相同步驟,實現(xiàn)批量化操作,極大的優(yōu)化了 CPU 消耗。

合并的代價即是耗時略有增加,我們通過快慢分離,只針對熱點數(shù)據(jù)請求中的邏輯操作進(jìn)行合并,去掉了耗時中的不穩(wěn)定因子,減少了耗時抖動。

請求合并

既然單機(jī)的邏輯操作性能已經(jīng)得到了極大的提升,那么前后端的網(wǎng)絡(luò)交互階段,包括接入層的打包解包、協(xié)議處理等環(huán)節(jié),成為了資源的主要消耗點。參考批量操作的經(jīng)驗,我們同樣使用批量化的技術(shù)來優(yōu)化性能――即將后臺訪問過來的單條請求 (Get) 在內(nèi)存層聚合成一次批量請求 (Batch Get)。

路由收斂

因為每個數(shù)據(jù)都是根據(jù)鍵值單獨進(jìn)行路由的,如果要進(jìn)行請求合并,我們就必須確保同一個批量請求內(nèi)的數(shù)據(jù),都會尋址到相同的 Paxos Group 上。因此,我們必須在內(nèi)存層將落到同一臺存儲機(jī)器上的 Get 請求聚合起來。我們首先在內(nèi)存層和存儲層采用了相同的路由算法,然后將內(nèi)存層的組數(shù)同存儲層的組數(shù)進(jìn)行對齊,來完成了這一目標(biāo)。

怎樣實踐微信后臺的海量數(shù)據(jù)冷熱分級架構(gòu)設(shè)計

相關(guān)工作

在設(shè)計的階段,我們充分的調(diào)研了業(yè)界的各類方案,大到系統(tǒng)的整體架構(gòu),小到具體的技術(shù)點。各種方案自有應(yīng)用場景、各有千秋,不能單純以好壞區(qū)別,我們同樣基于自己的業(yè)務(wù)場景,謹(jǐn)慎的選擇合適的方案,或者棄而不用。在此盡量敘述。

處理 SNS 類業(yè)務(wù)生成的數(shù)據(jù),業(yè)界有多種的冷熱分離架構(gòu)可以參考。我們以 Facebook 的 Cold Storage 系統(tǒng)舉例而言,它也是基于冷熱分層的想法,設(shè)計出了服務(wù)它們照片業(yè)務(wù)數(shù)據(jù)的存儲方案。不同的是它采用了軟硬件結(jié)合的方法,一方面定制專門的服務(wù)器(包括硬盤、電源等)和數(shù)據(jù)中心,一方面降低冷數(shù)據(jù)的備份數(shù)、增加糾刪碼等手段。

然而它們的經(jīng)驗我們是無法徹底套用的,主要兩種原因:我們可使用的機(jī)器機(jī)型是固定的,不存在自己定制硬件的條件。同時它處理的是照片這種大 value 的數(shù)據(jù)。而我們基本上是文本這種類型的小 value 數(shù)據(jù)。從前文提及的 TB 訪問量角度來看,它們處理的數(shù)據(jù)是容量瓶頸的,而我們處理的是 IO 瓶頸的,可以算是不太冷的冷數(shù)據(jù)帶來的挑戰(zhàn)。所以,我們只能實現(xiàn)自己的冷數(shù)據(jù)管理策略。

同樣,業(yè)界有諸多關(guān)于如何實現(xiàn)數(shù)據(jù)一致性的方案。包括我們微信自研的 Quorum 協(xié)議,它是一種 NWR 協(xié)議,采用異步同步的方式實現(xiàn)數(shù)據(jù)多副本。即然是異步同步,那在多副本達(dá)到最終一致,必然存在一個時間差,那么在單機(jī)出現(xiàn)離線的情況下,就會有一定概率導(dǎo)致數(shù)據(jù)的不可用。而我們追求的是在單點故障下,所有的數(shù)據(jù)都保證強(qiáng)可用性。

因此,我們采用了無主的去中心化的 Paxos Group 實現(xiàn)了這一目標(biāo),其中非租約是 PaxosStore 架構(gòu)的一個創(chuàng)新亮點。在故障時通常系統(tǒng)是抖動的,會有時斷時續(xù)的狀況,常見的租約做法在這種場景下容易出現(xiàn)反復(fù)切換主機(jī)而導(dǎo)致長期不可用,而 PaxosStore 的非租約結(jié)構(gòu)能夠輕松應(yīng)對,始終提供良好的服務(wù)。PaxosStore 核心代碼正在整理開源當(dāng)中,預(yù)計四季度會正式發(fā)布,同時該項目的底層框架也基于我們已開源的協(xié)程庫 github.com/libco。

看完上述內(nèi)容,你們對怎樣實踐微信后臺的海量數(shù)據(jù)冷熱分級架構(gòu)設(shè)計有進(jìn)一步的了解嗎?如果還想了解更多知識或者相關(guān)內(nèi)容,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。

當(dāng)前題目:怎樣實踐微信后臺的海量數(shù)據(jù)冷熱分級架構(gòu)設(shè)計
分享URL:http://muchs.cn/article8/gehoop.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供域名注冊、企業(yè)建站企業(yè)網(wǎng)站制作、品牌網(wǎng)站建設(shè)網(wǎng)站排名、全網(wǎng)營銷推廣

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站建設(shè)網(wǎng)站維護(hù)公司