第三章 中间件,3.1 万亿级数据洪峰下的分布式消息引擎(作者:冯嘉、誓嘉、尘央、牟羽)...
3.1 萬(wàn)億級(jí)數(shù)據(jù)洪峰下的分布式消息引擎
前言
通過(guò)簡(jiǎn)單回顧阿里中間件(Aliware)消息引擎的發(fā)展史,本文開篇于雙11消息引擎面臨的低延遲挑戰(zhàn),通過(guò)經(jīng)典的應(yīng)用場(chǎng)景闡述可能會(huì)面臨的問(wèn)題 - 響應(yīng)慢,雪崩,用戶體驗(yàn)差,繼而交易下跌。為了應(yīng)對(duì)這些不可控的洪峰數(shù)據(jù),中間件團(tuán)隊(duì)通過(guò)大量研究和實(shí)踐,推出了低延遲高可用解決方案,在分布式存儲(chǔ)領(lǐng)域具有一定的普適性。在此基礎(chǔ)上,通過(guò)對(duì)現(xiàn)有有限資源的規(guī)劃,又推出了分級(jí)的容量保障策略,通過(guò)限流、降級(jí),甚至熔斷技術(shù),能夠有效保障重點(diǎn)業(yè)務(wù)的高吞吐,成功的支撐集團(tuán)包括海外業(yè)務(wù)平緩舒暢地度過(guò)雙11高峰。與此同時(shí),在一些對(duì)高可靠、高可用要求極為苛刻的場(chǎng)景下,中間件團(tuán)隊(duì)又重點(diǎn)推出了基于多副本機(jī)制的高可用解決方案,能夠動(dòng)態(tài)識(shí)別機(jī)器宕機(jī)、機(jī)房斷網(wǎng)等災(zāi)難場(chǎng)景,自動(dòng)實(shí)現(xiàn)主備切換。整個(gè)切換過(guò)程對(duì)用戶透明,運(yùn)維開發(fā)人員無(wú)需干預(yù),極大地提升消息存儲(chǔ)的可靠性以及整個(gè)集群的高可用性。
?
1. 消息引擎家族史
阿里中間件消息引擎發(fā)展到今日,前前后后經(jīng)歷了三代演進(jìn)。第一代,推模式,數(shù)據(jù)存儲(chǔ)采用關(guān)系型數(shù)據(jù)庫(kù)。在這種模式下,消息具有很低的延遲特性,尤其在阿里淘寶這種高頻交易場(chǎng)景中,具有非常廣泛地應(yīng)用。第二代,拉模式,自研的專有消息存儲(chǔ)。能夠媲美Kafka的吞吐性能,但考慮到淘寶的應(yīng)用場(chǎng)景,尤其是其交易鏈路等高可靠場(chǎng)景,消息引擎并沒有一位的追求吞吐,而是將穩(wěn)定可靠放在首位。因?yàn)椴捎昧碎L(zhǎng)連接拉模式,在消息的實(shí)時(shí)方面絲毫不遜推模式。在前兩代經(jīng)歷了數(shù)年線上堪比工況的洗禮后,中間件團(tuán)隊(duì)于2011年研發(fā)了以拉模式為主,兼有推模式的高性能、低延遲消息引擎RocketMQ。并在2012年進(jìn)行了開源,經(jīng)歷了6年雙11核心交易鏈路檢驗(yàn),愈久彌堅(jiān)。目前已經(jīng)捐贈(zèng)給阿帕奇基金會(huì)(ASF),有望成為繼ActiveMQ,Kafka之后,Apache社區(qū)第三個(gè)重量級(jí)分布式消息引擎。時(shí)至今日,RocketMQ很好的服務(wù)了阿里集團(tuán)大大小小上千個(gè)應(yīng)用,在雙11當(dāng)天,更有不可思議的萬(wàn)億級(jí)消息流轉(zhuǎn),為集團(tuán)大中臺(tái)的穩(wěn)定發(fā)揮了舉足輕重的作用。
2. 低延遲可用性探索
疾風(fēng)吹征帆,倏爾向空沒。千里在俄頃,三江坐超忽。—孟浩然
?
2.1 低延遲與可用性
隨著Java語(yǔ)言生態(tài)的完善,JVM性能的提高,C和C++已經(jīng)不再是低延遲場(chǎng)景唯一的選擇。本章節(jié)重點(diǎn)介紹RocketMQ在低延遲可用性方面的一些探索。
應(yīng)用程序的性能度量標(biāo)準(zhǔn)一般從吞吐量和延遲兩方面考量。吞吐量是指程序在一段時(shí)間內(nèi)能處理的請(qǐng)求數(shù)量。延遲是指端到端的響應(yīng)時(shí)間。低延遲在不同的環(huán)境下有不同的定義,比如在聊天應(yīng)用中低延遲可以定義為200ms內(nèi),在交易系統(tǒng)中定義為10ms內(nèi)。相對(duì)于吞吐量,延遲會(huì)受到很多因素的影響,如CPU、網(wǎng)絡(luò)、內(nèi)存、操作系統(tǒng)等。
根據(jù)Little's law,當(dāng)延遲變高時(shí),駐留在分布式系統(tǒng)中的請(qǐng)求會(huì)劇增,導(dǎo)致某些節(jié)點(diǎn)不可用,不可用的狀態(tài)甚至?xí)U(kuò)散至其它節(jié)點(diǎn),造成整個(gè)系統(tǒng)的服務(wù)能力喪失,這種場(chǎng)景又俗稱雪崩。所以打造低延遲的應(yīng)用程序,對(duì)提升整個(gè)分布式系統(tǒng)可用性有很大的裨益。
?
2.2 低延遲探索之路
RocketMQ作為一款消息引擎,最大的作用是異步解耦和削峰填谷。一方面,分布式應(yīng)用會(huì)利用RocketMQ來(lái)進(jìn)行異步解耦,應(yīng)用程序可以自如地?cái)U(kuò)容和縮容。另一方面,當(dāng)洪峰數(shù)據(jù)來(lái)臨時(shí),大量的消息需要堆積到RocketMQ中,后端程序可以根據(jù)自己的消費(fèi)速度來(lái)進(jìn)行數(shù)據(jù)的讀取。所以保證RocketMQ寫消息鏈路的低延遲至關(guān)重要。
在今年雙11期間,天貓發(fā)布了紅包火山的新玩法。該游戲?qū)ρ舆t非常敏感,只能容忍50ms內(nèi)的延遲,在壓測(cè)初期RocketMQ寫消息出現(xiàn)了大量50~500ms的延遲,導(dǎo)致了在紅包噴發(fā)的高峰出現(xiàn)大量的失敗,嚴(yán)重影響前端業(yè)務(wù)。下圖為壓測(cè)紅包集群在壓測(cè)時(shí)寫消息延遲熱力圖統(tǒng)計(jì)。
作為一款純Java語(yǔ)言開發(fā)的消息引擎,RocketMQ自主研發(fā)的存儲(chǔ)組件,依賴Page Cache進(jìn)行加速和堆積,意味著它的性能會(huì)受到JVM、GC、內(nèi)核、Linux內(nèi)存管理機(jī)制、文件IO等因素的影響。如下圖所示,一條消息從客戶端發(fā)送出,到最終落盤持久化,每個(gè)環(huán)節(jié)都有產(chǎn)生延遲的風(fēng)險(xiǎn)。通過(guò)對(duì)線上數(shù)據(jù)的觀察,RocketMQ寫消息鏈路存在偶發(fā)的高達(dá)數(shù)秒的延遲。
2.2.1? JVM停頓
JVM(Java虛擬機(jī))在運(yùn)行過(guò)程中會(huì)產(chǎn)生很多停頓,常見的有GC、JIT、取消偏向鎖(RevokeBias)、RedefineClasses(AOP)等。對(duì)應(yīng)用程序影響最大的則是GC停頓。RocketMQ盡量避免Full GC,但Minor GC帶來(lái)的停頓是難以避免的。針對(duì)GC調(diào)優(yōu)是一個(gè)很伽利略的問(wèn)題,需要通過(guò)大量的測(cè)試來(lái)幫助應(yīng)用程序調(diào)整GC參數(shù),比如可以通過(guò)調(diào)整堆大小,GC的時(shí)機(jī),優(yōu)化數(shù)據(jù)結(jié)構(gòu)等手段進(jìn)行調(diào)優(yōu)。
對(duì)于其它JVM停頓,可以通過(guò)-XX:+PrintGCApplicationStoppedTime將JVM停頓時(shí)間輸出到GC日志中。通過(guò)-XX:+PrintSafepointStatistics -XX: PrintSafepointStatisticsCount=1輸出具體的停頓原因,并進(jìn)行針對(duì)性的優(yōu)化。比如在RocketMQ中發(fā)現(xiàn)取RevokeBias產(chǎn)生了大量的停頓,通過(guò)-XX:-UseBiasedLocking關(guān)閉了偏向鎖特性。
另外,GC日志的輸出會(huì)發(fā)生文件IO,有時(shí)候也會(huì)造成不必要的停頓,可以將GC日志輸出到tmpfs(內(nèi)存文件系統(tǒng))中,但tmpfs會(huì)消耗內(nèi)存,為了避免內(nèi)存被浪費(fèi)可以使用-XX:+UseGCLogFileRotation滾動(dòng)GC日志。
除了GC日志會(huì)產(chǎn)生文件IO,JVM會(huì)將jstat命令需要的一些統(tǒng)計(jì)數(shù)據(jù)輸出到/tmp(hsperfdata)目錄下,可通過(guò)-XX:+PerfDisableSharedMem關(guān)閉該特性,并使用JMX來(lái)代替jstat。
?
2.2.2? 鎖——同步的“利”器
作為一種臨界區(qū)的保護(hù)機(jī)制,鎖被廣泛用于多線程應(yīng)用程序的開發(fā)中。但鎖是一把雙刃劍,過(guò)多或不正確的使用鎖會(huì)導(dǎo)致多線程應(yīng)用的性能下降。
Java中的鎖默認(rèn)采用的是非公平鎖,加鎖時(shí)不考慮排隊(duì)問(wèn)題,直接嘗試獲取鎖,若獲取失敗自動(dòng)進(jìn)行排隊(duì)。非公平鎖會(huì)導(dǎo)致線程等待時(shí)間過(guò)長(zhǎng),延遲變高。倘若采取公平鎖,又會(huì)對(duì)應(yīng)用帶來(lái)較大性能損失。
另一方面,同步會(huì)引起上下文切換,這會(huì)帶來(lái)一定的開銷。上下文切換一般是微秒級(jí),但當(dāng)線程數(shù)過(guò)多,競(jìng)爭(zhēng)壓力大時(shí),會(huì)產(chǎn)生數(shù)十毫秒級(jí)別的開銷。可通過(guò)LockSupport.park來(lái)模擬產(chǎn)生上下文切換進(jìn)行測(cè)試。
為了避免鎖帶來(lái)的延遲,利用CAS原語(yǔ)將RocketMQ核心鏈路無(wú)鎖化,在降低延遲的同時(shí)顯著提高吞吐量。
?
2.2.3? 內(nèi)存——沒那么快
受限于Linux的內(nèi)存管理機(jī)制,應(yīng)用程序訪問(wèn)內(nèi)存時(shí)有時(shí)候會(huì)產(chǎn)生高延遲。Linux中內(nèi)存主要有匿名內(nèi)存和Page Cache兩種。
Linux會(huì)用盡可能多的內(nèi)存來(lái)做緩存,大多數(shù)情形下,服務(wù)器可用內(nèi)存都較少。可用內(nèi)存較少時(shí),應(yīng)用程序申請(qǐng)或者訪問(wèn)新的內(nèi)存頁(yè)會(huì)引發(fā)內(nèi)存回收,當(dāng)后臺(tái)內(nèi)存回收的速度不及分配內(nèi)存的速度時(shí),會(huì)進(jìn)入直接回收(Direct Reclaim),應(yīng)用程序會(huì)自旋等待內(nèi)存回收完畢,產(chǎn)生巨大的延遲,如下圖所示。
另一方面,內(nèi)核也會(huì)回收匿名內(nèi)存頁(yè),匿名內(nèi)存頁(yè)被換出后下一次訪問(wèn)會(huì)產(chǎn)生文件IO,導(dǎo)致延遲,如下圖所示。
上述兩種情況產(chǎn)生的延遲可以通過(guò)內(nèi)核參數(shù)(vm.extra_free_kbytes和vm.swappiness)調(diào)優(yōu)加以避免。
Linux對(duì)內(nèi)存的管理一般是以頁(yè)為單位,一頁(yè)一般為4k大小,當(dāng)在同一頁(yè)內(nèi)存上產(chǎn)生讀寫競(jìng)爭(zhēng)時(shí),會(huì)產(chǎn)生延遲,對(duì)于這種情況,需要應(yīng)用程序自行協(xié)調(diào)內(nèi)存的訪問(wèn)加以避免。
?
2.2.4? Page Cache——利與弊??
Page Cache是文件的緩存,用于加速對(duì)文件的讀寫,它為RocketMQ提供了更強(qiáng)大的堆積能力。RocketMQ將數(shù)據(jù)文件映射到內(nèi)存中,寫消息的時(shí)候首先寫入Page Cache,并通過(guò)異步刷盤的模式將消息持久化(同時(shí)也支持同步刷盤),消息可以直接從Page Cache中讀取,這也是業(yè)界分布式存儲(chǔ)產(chǎn)品通常采用的模式,如下圖所示:
該模式大多數(shù)情況讀寫速度都比較迅速,但當(dāng)遇到操作系統(tǒng)進(jìn)行臟頁(yè)回寫,內(nèi)存回收,內(nèi)存換入換出等情形時(shí),會(huì)產(chǎn)生較大的讀寫延遲,造成存儲(chǔ)引擎偶發(fā)的高延遲。
針對(duì)這種現(xiàn)象,RocketMQ采用了多種優(yōu)化技術(shù),比如內(nèi)存預(yù)分配,文件預(yù)熱,mlock系統(tǒng)調(diào)用,讀寫分離等,來(lái)保證利用Page Cache優(yōu)點(diǎn)的同時(shí),消除其帶來(lái)的延遲。
?
2.3 優(yōu)化成果
RocketMQ通過(guò)對(duì)上述情況的優(yōu)化,成功消除了寫消息高延遲的情形,并通過(guò)了今年雙11的考驗(yàn)。優(yōu)化后寫消息耗時(shí)熱力圖如下圖所示。
優(yōu)化后RocketMQ寫消息延遲99.995%在1ms內(nèi),100%在100ms內(nèi),如下圖所示。
3. 容量保障三大法寶
他強(qiáng)任他強(qiáng),清風(fēng)拂山崗。他橫任他橫,明月照大江。—九陽(yáng)真經(jīng)心法
?
有了低延遲的優(yōu)化保障,并不意味著消息引擎就可以高枕無(wú)憂。為了給應(yīng)用帶來(lái)如絲般順滑的體驗(yàn),消息引擎必須進(jìn)行靈活的容量規(guī)劃。如何讓系統(tǒng)能夠在洶涌澎湃的流量洪峰面前談笑風(fēng)生?降級(jí)、限流、熔斷三大法寶便有了用武之地。丟卒保車,以降級(jí)、暫停邊緣服務(wù)、組件為代價(jià)保障核心服務(wù)的資源,以系統(tǒng)不被突發(fā)流量擊垮為第一要?jiǎng)?wù)。正所謂,他強(qiáng)任他強(qiáng),清風(fēng)拂山崗。他橫任他橫,明月照大江!
從架構(gòu)的穩(wěn)定性角度看,在有限資源的情況下,所能提供的單位時(shí)間服務(wù)能力也是有限的。假如超過(guò)承受能力,可能會(huì)帶來(lái)整個(gè)服務(wù)的停頓,應(yīng)用的Crash,進(jìn)而可能將風(fēng)險(xiǎn)傳遞給服務(wù)調(diào)用方造成整個(gè)系統(tǒng)的服務(wù)能力喪失,進(jìn)而引發(fā)雪崩。另外,根據(jù)排隊(duì)理論,具有延遲的服務(wù)隨著請(qǐng)求量的不斷提升,其平均響應(yīng)時(shí)間也會(huì)迅速提升,為了保證服務(wù)的SLA,有必要控制單位時(shí)間的請(qǐng)求量。這就是限流為什么愈發(fā)重要的原因。限流這個(gè)概念,在學(xué)術(shù)界又被稱之為Traffic Shaping。最早起源于網(wǎng)絡(luò)通訊領(lǐng)域,典型的有漏桶(leaky bucket)算法和令牌桶(token bucket)算法。
漏桶算法基本思路是有一個(gè)桶(會(huì)漏水),水以恒定速率滴出,上方會(huì)有水滴(請(qǐng)求)進(jìn)入水桶。如果上方水滴進(jìn)入速率超過(guò)水滴出的速率,那么水桶就會(huì)溢出,即請(qǐng)求過(guò)載。
令牌桶算法基本思路是同樣也有一個(gè)桶,令牌以恒定速率放入桶,桶內(nèi)的令牌數(shù)有上限,每個(gè)請(qǐng)求會(huì)acquire一個(gè)令牌,如果某個(gè)請(qǐng)求來(lái)到而桶內(nèi)沒有令牌了,則這個(gè)請(qǐng)求是過(guò)載的。很顯然,令牌桶會(huì)存在請(qǐng)求突發(fā)激增的問(wèn)題。
無(wú)論是漏桶、令牌桶,抑或其它變種算法,都可以看做是一種控制速度的限流,工程領(lǐng)域如Guava里的RateLimiter,Netty里的TrafficShaping等也都屬于此。除此之外,還有一種控制并發(fā)的限流模式,如操作系統(tǒng)里的信號(hào)量,JDK里的Semaphore。
異步解耦,削峰填谷,作為消息引擎的看家本領(lǐng),Try your best本身就是其最初的設(shè)計(jì)初衷(RPC、應(yīng)用網(wǎng)關(guān)、容器等場(chǎng)景下,控制速度應(yīng)成為流控首選)。但即便如此,一些必要的流控還是需要考量。不過(guò)與前面介紹的不同,RocketMQ中并沒有內(nèi)置Guava、Netty等拆箱即用的速度流控組件。而是通過(guò)借鑒排隊(duì)理論,對(duì)其中的慢請(qǐng)求進(jìn)行容錯(cuò)處理。這里的慢請(qǐng)求是指排隊(duì)等待時(shí)間以及服務(wù)時(shí)間超過(guò)某個(gè)閾值的請(qǐng)求。對(duì)于離線應(yīng)用場(chǎng)景,容錯(cuò)處理就是利用滑動(dòng)窗口機(jī)制,通過(guò)緩慢縮小窗口的手段,來(lái)減緩從服務(wù)端拉的頻率以及消息大小,降低對(duì)服務(wù)端的影響。而對(duì)于那些高頻交易,數(shù)據(jù)復(fù)制場(chǎng)景,則采取了快速失敗策略,既能預(yù)防應(yīng)用連鎖的資源耗盡而引發(fā)的應(yīng)用雪崩,又能有效降低服務(wù)端壓力,為端到端低延遲帶來(lái)可靠保障。
服務(wù)降級(jí)是一種典型的丟卒保車,二八原則實(shí)踐。而降級(jí)的手段也無(wú)外乎關(guān)閉,下線等“簡(jiǎn)單粗暴”的操作。降級(jí)目標(biāo)的選擇,更多來(lái)自于服務(wù)QoS的定義。消息引擎早期對(duì)于降級(jí)的處理主要來(lái)自兩方面,一方面來(lái)自于用戶數(shù)據(jù)的收集,另一方面來(lái)自引擎組件的服務(wù)QoS設(shè)定。對(duì)于前者,通過(guò)運(yùn)維管控系統(tǒng)推送應(yīng)用自身QoS數(shù)據(jù),一般會(huì)輸出如下表格。而引擎組件的服務(wù)QoS,如服務(wù)于消息問(wèn)題追溯的鏈路軌跡組件,對(duì)于核心功能來(lái)說(shuō),定級(jí)相對(duì)較低,可在洪峰到來(lái)之前提前關(guān)閉。
談到熔斷,不得不提經(jīng)典的電力系統(tǒng)中的保險(xiǎn)絲,當(dāng)負(fù)載過(guò)大,或者電路發(fā)生故障或異常時(shí),電流會(huì)不斷升高,為防止升高的電流有可能損壞電路中的某些重要器件或貴重器件,燒毀電路甚至造成火災(zāi)。保險(xiǎn)絲會(huì)在電流異常升高到一定的高度和熱度的時(shí)候,自身熔斷切斷電流,從而起到保護(hù)電路安全運(yùn)行的作用。
同樣,在分布式系統(tǒng)中,如果調(diào)用的遠(yuǎn)程服務(wù)或者資源由于某種原因無(wú)法使用時(shí),沒有這種過(guò)載保護(hù),就會(huì)導(dǎo)致請(qǐng)求的資源阻塞在服務(wù)器上等待從而耗盡系統(tǒng)或者服務(wù)器資源。很多時(shí)候剛開始可能只是系統(tǒng)出現(xiàn)了局部的、小規(guī)模的故障,然而由于種種原因,故障影響的范圍越來(lái)越大,最終導(dǎo)致了全局性的后果。而這種過(guò)載保護(hù)就是大家俗稱的熔斷器(Circuit Breaker)。Netflix公司為了解決該問(wèn)題,開源了它們的熔斷解決方案Hystrix。
上述三幅圖,描述了系統(tǒng)從初始的健康狀態(tài)到高并發(fā)場(chǎng)景下阻塞在下游的某個(gè)關(guān)鍵依賴組件的場(chǎng)景。這種情況很容易誘發(fā)雪崩效應(yīng)。而通過(guò)引入Hystrix的熔斷機(jī)制,讓應(yīng)用快速失敗,繼而能夠避免最壞情況的發(fā)生。
借鑒Hystrix思路,中間件團(tuán)隊(duì)自研了一套消息引擎熔斷機(jī)制。在大促壓測(cè)備戰(zhàn)期間,曾經(jīng)出現(xiàn)過(guò)由于機(jī)器硬件設(shè)備導(dǎo)致服務(wù)不可用。如果采用常規(guī)的容錯(cuò)手段,是需要等待30秒時(shí)間,不可用機(jī)器才能從列表里被摘除。但通過(guò)這套熔斷機(jī)制,能在毫秒范圍內(nèi)識(shí)別并隔離異常服務(wù)。進(jìn)一步提升了引擎的可用性。
?
4. 高可用解決方案
昔之善戰(zhàn)者,先為不可勝,以待敵之可勝。不可勝在己,可勝在敵。故善戰(zhàn)者,能為不可勝,不能使敵之必可勝。故曰:勝可知,而不可為。—孫武
雖然有了容量保障的三大法寶作為依托,但隨著消息引擎集群規(guī)模的不斷上升,到達(dá)一定程度后,集群中機(jī)器故障的可能性隨之提高,嚴(yán)重降低消息的可靠性以及系統(tǒng)的可用性。與此同時(shí),基于多機(jī)房部署的集群模式也會(huì)引發(fā)機(jī)房斷網(wǎng),進(jìn)一步降低消息系統(tǒng)的可用性。為此,阿里中間件(Aliware)重點(diǎn)推出了基于多副本的高可用解決方案,動(dòng)態(tài)識(shí)別機(jī)器故障、機(jī)房斷網(wǎng)等災(zāi)難場(chǎng)景,實(shí)現(xiàn)故障自動(dòng)恢復(fù);整個(gè)恢復(fù)過(guò)程對(duì)用戶透明,無(wú)需運(yùn)維人員干預(yù),極大地提升了消息存儲(chǔ)的可靠性,保障了整個(gè)集群的高可用性。
高可用性幾乎是每個(gè)分布式系統(tǒng)在設(shè)計(jì)時(shí)必須要考慮的一個(gè)重要特性,在遵循CAP原則(即:一致性、可用性和分區(qū)容錯(cuò)性三者無(wú)法在分布式系統(tǒng)中被同時(shí)滿足,并且最多只能滿足其中兩個(gè))基礎(chǔ)上,業(yè)界也提出了一些針對(duì)分布式系統(tǒng)通用的高可用解決方案,如下圖所示:
其中,行代表了分布式系統(tǒng)中通用的高可用解決方案,包括冷備、Master/Slave、Master/Master、兩階段提交以及基于Paxos算法的解決方案;列代表了分布式系統(tǒng)所關(guān)心的各項(xiàng)指標(biāo),包括數(shù)據(jù)一致性、事務(wù)支持程度、數(shù)據(jù)延遲、系統(tǒng)吞吐量、數(shù)據(jù)丟失可能性、故障自動(dòng)恢復(fù)方式。
從圖中可以看出,不同的解決方案對(duì)各項(xiàng)指標(biāo)的支持程度各有側(cè)重。基于CAP原則,很難設(shè)計(jì)出一種高可用方案能同時(shí)夠滿足所有指標(biāo)的最優(yōu)值,以Master/Slave為例,一般滿足如下幾個(gè)特性:
1) Slave是Master的備份,可以根據(jù)數(shù)據(jù)的重要程度設(shè)置Slave的個(gè)數(shù)。
數(shù)據(jù)寫請(qǐng)求命中Master,讀請(qǐng)求可命中Master或者Slave。
2) 寫請(qǐng)求命中Master之后,數(shù)據(jù)可通過(guò)同步或者異步的方式從Master復(fù)制到Slave上;其中同步復(fù)制模式需要保證Master和Slave均寫成功后才反饋給客戶端成功;異步復(fù)制模式只需要保證Master寫成功即可反饋給客戶端成功。
數(shù)據(jù)通過(guò)同步或者異步方式從Master復(fù)制到Slave上,因此Master/Slave結(jié)構(gòu)至少能保證數(shù)據(jù)的最終一致性;異步復(fù)制模式下,數(shù)據(jù)在Master寫成功后即可反饋給客戶端成功,因此系統(tǒng)擁有較低的延遲和較高的吞吐量,但同時(shí)會(huì)帶來(lái)Master故障丟數(shù)據(jù)的可能性;如期望異步復(fù)制模式下Master故障時(shí)數(shù)據(jù)仍不丟,Slave只能以Read-Only的方式等待Master的恢復(fù),即延長(zhǎng)了系統(tǒng)的故障恢復(fù)時(shí)間。相反,Master/Slave結(jié)構(gòu)中的同步復(fù)制模式會(huì)以增大數(shù)據(jù)寫入延遲、降低系統(tǒng)吞吐量的代價(jià)來(lái)保證機(jī)器故障時(shí)數(shù)據(jù)不丟,同時(shí)降低系統(tǒng)故障恢復(fù)時(shí)間。
?
5. RocketMQ高可用架構(gòu)
RocketMQ基于原有多機(jī)房部署的集群模式,利用分布式鎖和通知機(jī)制,借助Controller組件,設(shè)計(jì)并實(shí)現(xiàn)了Master/Slave結(jié)構(gòu)的高可用架構(gòu),如下圖所示:
其中,Zookeeper作為分布式調(diào)度框架,需要至少在A、B、C三個(gè)機(jī)房部署以保證其高可用,并為RocketMQ高可用架構(gòu)提供如下功能:
1) 維護(hù)持久節(jié)點(diǎn)(PERSISTENT),保存主備狀態(tài)機(jī);
2) 維護(hù)臨時(shí)節(jié)點(diǎn)(EPHEMERAL),保存RocketMQ的當(dāng)前狀態(tài);
3) 當(dāng)主備狀態(tài)機(jī)、服務(wù)端當(dāng)前狀態(tài)發(fā)生變更時(shí),通知對(duì)應(yīng)的觀察者。
RocketMQ以Master/Slave結(jié)構(gòu)實(shí)現(xiàn)多機(jī)房對(duì)等部署,消息的寫請(qǐng)求會(huì)命中Master,然后通過(guò)同步或者異步方式復(fù)制到Slave上進(jìn)行持久化存儲(chǔ);消息的讀請(qǐng)求會(huì)優(yōu)先命中Master,當(dāng)消息堆積導(dǎo)致磁盤壓力大時(shí),讀請(qǐng)求轉(zhuǎn)移至Slave。
RocketMQ直接與Zookeeper進(jìn)行交互,體現(xiàn)在:
1) 以臨時(shí)節(jié)點(diǎn)的方式向Zookeeper匯報(bào)當(dāng)前狀態(tài);
2) 作為觀察者監(jiān)聽Zookeeper上主備狀態(tài)機(jī)的變更。當(dāng)發(fā)現(xiàn)主備狀態(tài)機(jī)變化時(shí),根據(jù)最新的狀態(tài)機(jī)更改當(dāng)前狀態(tài);
RocketMQ HA Controller是消息引擎高可用架構(gòu)中降低系統(tǒng)故障恢復(fù)時(shí)間的無(wú)狀態(tài)組件,在A、B、C三個(gè)機(jī)房分布式部署,其主要職責(zé)體現(xiàn)在:
1) 作為觀察者監(jiān)聽Zookeeper 上RocketMQ當(dāng)前狀態(tài)的變更;
2) 根據(jù)集群的當(dāng)前狀態(tài),控制主備狀態(tài)機(jī)的切換并向Zookeeper匯報(bào)最新主備狀態(tài)機(jī)。
出于對(duì)系統(tǒng)復(fù)雜性以及消息引擎本身對(duì)CAP原則適配的考慮,RocketMQ高可用架構(gòu)的設(shè)計(jì)采用了Master/Slave結(jié)構(gòu),在提供低延遲、高吞吐量消息服務(wù)的基礎(chǔ)上,采用主備同步復(fù)制的方式避免故障時(shí)消息的丟失。數(shù)據(jù)同步過(guò)程中,通過(guò)維護(hù)一個(gè)遞增的全局唯一SequenceID來(lái)保證數(shù)據(jù)強(qiáng)一致。同時(shí)引入故障自動(dòng)恢復(fù)機(jī)制以降低故障恢復(fù)時(shí)間,提升系統(tǒng)的可用性。
?
5.1 可用性評(píng)估
系統(tǒng)可用性(Availability)是信息工業(yè)界用來(lái)衡量一個(gè)信息系統(tǒng)提供持續(xù)服務(wù)的能力,它表示的是在給定時(shí)間區(qū)間內(nèi)系統(tǒng)或者系統(tǒng)某一能力在特定環(huán)境中能夠正常工作的概率。簡(jiǎn)單地說(shuō), 可用性是平均故障間隔時(shí)間(MTBF)除以平均故障間隔時(shí)間(MTBF)和平均故障修復(fù)時(shí)間(MTTR)之和所得的結(jié)果, 即:
通常業(yè)界習(xí)慣用N個(gè)9來(lái)表征系統(tǒng)可用性,比如99.9%代表3個(gè)9的可用性,意味著全年不可用時(shí)間在8.76小時(shí)以內(nèi);99.999%代表5個(gè)9的可用性,意味著全年不可用時(shí)間必須保證在5.26分鐘以內(nèi),缺少故障自動(dòng)恢復(fù)機(jī)制的系統(tǒng)將很難達(dá)到5個(gè)9的高可用性。
?
5.2 RocketMQ 高可用保障
通過(guò)可用性計(jì)算公式可以看出,要提升系統(tǒng)的可用性,需要在保障系統(tǒng)健壯性以延長(zhǎng)平均無(wú)故障時(shí)間的基礎(chǔ)上,進(jìn)一步加強(qiáng)系統(tǒng)的故障自動(dòng)恢復(fù)能力以縮短平均故障修復(fù)時(shí)間。RocketMQ高可用架構(gòu)設(shè)計(jì)并實(shí)現(xiàn)了Controller組件,按照單主狀態(tài)、異步復(fù)制狀態(tài)、半同步狀態(tài)以及最終的同步復(fù)制狀態(tài)的有限狀態(tài)機(jī)進(jìn)行轉(zhuǎn)換。在最終的同步復(fù)制狀態(tài)下,Master和Slave任一節(jié)點(diǎn)故障時(shí),其它節(jié)點(diǎn)能夠在秒級(jí)時(shí)間內(nèi)切換到單主狀態(tài)繼續(xù)提供服務(wù)。相比于之前人工介入重啟來(lái)恢復(fù)服務(wù),RokcetMQ高可用架構(gòu)賦予了系統(tǒng)故障自動(dòng)恢復(fù)的能力,能極大縮短平均故障恢復(fù)時(shí)間,提升系統(tǒng)的可用性。
?
下圖描述了RocketMQ高可用架構(gòu)中有限狀態(tài)機(jī)的轉(zhuǎn)換:
- 第一個(gè)節(jié)點(diǎn)啟動(dòng)后,Controller控制狀態(tài)機(jī)切換為單主狀態(tài),通知啟動(dòng)節(jié)點(diǎn)以Master角色提供服務(wù)。
- 第二個(gè)節(jié)點(diǎn)啟動(dòng)后,Controller控制狀態(tài)機(jī)切換成異步復(fù)制狀態(tài)。Master通過(guò)異步方式向Slave復(fù)制數(shù)據(jù)。
- 當(dāng)Slave的數(shù)據(jù)即將趕上Master,Controller控制狀態(tài)機(jī)切換成半同步狀態(tài),此時(shí)命中Master的寫請(qǐng)求會(huì)被Hold住,直到Master以異步方式向Slave復(fù)制了所有差異的數(shù)據(jù)。
- 當(dāng)半同步狀態(tài)下Slave的數(shù)據(jù)完全趕上Master時(shí),Controller控制狀態(tài)機(jī)切換成同步復(fù)制模式,Mater開始以同步方式向Slave復(fù)制數(shù)據(jù)。該狀態(tài)下任一節(jié)點(diǎn)出現(xiàn)故障,其它節(jié)點(diǎn)能夠在秒級(jí)內(nèi)切換到單主狀態(tài)繼續(xù)提供服務(wù)。
Controller組件控制RocketMQ按照單主狀態(tài),異步復(fù)制狀態(tài),半同步狀態(tài),同步復(fù)制狀態(tài)的順序進(jìn)行狀態(tài)機(jī)切換。中間狀態(tài)的停留時(shí)間與主備之間的數(shù)據(jù)差異以及網(wǎng)絡(luò)帶寬有關(guān),但最終都會(huì)穩(wěn)定在同步復(fù)制狀態(tài)下。
?
展望
雖然經(jīng)歷了這么多年線上堪比工況的苛刻檢驗(yàn),阿里中間件消息引擎仍然存在著優(yōu)化空間,如團(tuán)隊(duì)正嘗試通過(guò)優(yōu)化存儲(chǔ)算法、跨語(yǔ)言調(diào)用等策略進(jìn)一步降低消息低延遲存儲(chǔ)。面對(duì)移動(dòng)物聯(lián)網(wǎng)、大數(shù)據(jù)、VR等新興場(chǎng)景,面對(duì)席卷全球的開放與商業(yè)化生態(tài),團(tuán)隊(duì)開始著手打造第4代消息引擎,多級(jí)協(xié)議QoS,跨網(wǎng)絡(luò)、跨終端、跨語(yǔ)言支持,面向在線應(yīng)用更低的響應(yīng)時(shí)間,面向離線應(yīng)用更高的吞吐,秉持取之于開源,回饋于開源的思想,相信RocektMQ朝著更健康的生態(tài)發(fā)展。
參考文獻(xiàn)
[1]Ryan Barrett.?http://snarfed.org/transactions_across_datacenters_io.html
[2]http://www.slideshare.net/vimal25792/leaky-bucket-tocken-buckettraffic-shaping
[3]http://systemdesigns.blogspot.com/2015/12/rate-limiter.html
[4]Little J D C, Graves S C. Little's law[M]//Building intuition. Springer US, 2008: 81-100.
[5]https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html-single/Performance_Tuning_Guide/index.html
[6]http://highscalability.com/blog/2012/3/12/google-taming-the-long-latency-tail-when-more-machines-equal.html
[7]https://www.azul.com/files/EnablingJavaInLatencySensitiveEnvs_DotCMSBootcamp_Nashville_23Oct20141.pdf
總結(jié)
以上是生活随笔為你收集整理的第三章 中间件,3.1 万亿级数据洪峰下的分布式消息引擎(作者:冯嘉、誓嘉、尘央、牟羽)...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: java intfilter_Java
- 下一篇: java cv bgr2gray_CV_