vivo 超大數(shù)據(jù)規(guī)模分布式消息中間件架構(gòu)演進(jìn)實(shí)踐
一、vivo 架構(gòu)演進(jìn)實(shí)踐
1. 業(yè)務(wù)背景
首先來介紹一下相關(guān)業(yè)務(wù)背景。
上圖展示了 vivo 互聯(lián)網(wǎng)大數(shù)據(jù)場(chǎng)景下全鏈路架構(gòu)。以終端用戶為起點(diǎn),經(jīng)過統(tǒng)一的數(shù)據(jù)集成,數(shù)據(jù)進(jìn)入統(tǒng)一數(shù)據(jù)接入層,再通過 ETL 的海量計(jì)算和實(shí)時(shí)的數(shù)據(jù)分揀,將數(shù)據(jù)存入實(shí)時(shí)數(shù)倉(cāng)和離線數(shù)倉(cāng),最終賦能到下游的業(yè)務(wù)產(chǎn)品。這個(gè)架構(gòu)是當(dāng)前主流的架構(gòu)體系。在此架構(gòu)中分布式消息中間件(Kafka/Pulsar)致力于為用戶提供一套在大數(shù)據(jù)場(chǎng)景下高吞吐、低延時(shí)、高可靠、高擴(kuò)展、全托管、安全的統(tǒng)一數(shù)據(jù)接入服務(wù)和實(shí)時(shí)數(shù)倉(cāng)服務(wù)。
我們認(rèn)為,考慮 AI 大模型的變與不變,核心在于數(shù)據(jù),對(duì)數(shù)據(jù)穩(wěn)定性要求的日益提高也使得我們開始思考下一代消息中間件應(yīng)該是什么樣子的。圖中展示了 vivo 的技術(shù)演進(jìn)迭代路徑。vivo 消息中間件項(xiàng)目從 2019 年立項(xiàng),2021 年完成功能建設(shè),項(xiàng)目進(jìn)入快速發(fā)展的階段,2022 年項(xiàng)目達(dá)到了成熟運(yùn)營(yíng)的水平。項(xiàng)目建設(shè)過程中,2021 年我們發(fā)現(xiàn) Kafka 在超大數(shù)據(jù)規(guī)模場(chǎng)景下存在一些架構(gòu)上的缺陷,所以我們團(tuán)隊(duì)開始對(duì)下一代分布式消息中間件 Palsar 進(jìn)行調(diào)研,與之相關(guān)的項(xiàng)目在 2022 年正式立項(xiàng)。截至今年,經(jīng)過一年的運(yùn)營(yíng)和引流,目前每天 Palsar 集群處理的消息量在 2 萬(wàn)億左右。
統(tǒng)一數(shù)據(jù)接入層的上一層是統(tǒng)一數(shù)據(jù)采集層。vivo 在統(tǒng)一數(shù)據(jù)采集層會(huì)做一些高可用的保障。
(1)離線鏈路寫 HDFS 實(shí)現(xiàn)分鐘級(jí)主備切換
對(duì)于離線鏈路,做到了分鐘級(jí)的主備切換,這依賴于 manager 服務(wù)能實(shí)時(shí)檢測(cè)HDFS 集群的健康狀態(tài)并實(shí)時(shí)同步到 agent,當(dāng) HDFS 集群出現(xiàn)故障時(shí),同時(shí)通知到上游的統(tǒng)一采集層以及下游的 ETL,在分鐘級(jí)的時(shí)間段內(nèi)切換到備份集群上,實(shí)現(xiàn)在離線鏈路上的高可用保障。
(2)高優(yōu)業(yè)務(wù)雙鏈路容災(zāi)快速切換
目前對(duì)于數(shù)據(jù)接入有實(shí)時(shí)鏈路和離線鏈路兩套數(shù)據(jù)接入架構(gòu),并會(huì)對(duì)實(shí)時(shí)鏈路和離線鏈路接入的數(shù)據(jù)做分鐘級(jí)對(duì)照校驗(yàn),從而實(shí)現(xiàn)實(shí)時(shí)和離線兩條鏈路保障高優(yōu)業(yè)務(wù)的容災(zāi)切換。
2. 運(yùn)營(yíng)現(xiàn)狀
目前 vivo 內(nèi)部 Kafka 集群日均處理消息數(shù)量達(dá)到了 20 萬(wàn)億+,Palsar 集群日均處理消息數(shù)達(dá)到了萬(wàn)億+,在這樣超大數(shù)據(jù)規(guī)模的場(chǎng)景下,我們還與業(yè)務(wù)團(tuán)隊(duì)簽署了 SLA 四個(gè) 9 的高可用的保障協(xié)議,以確保用戶的高可用,同時(shí)實(shí)現(xiàn)降本增效。如圖所示,經(jīng)過三年建設(shè),我們的單機(jī)利用率提升了 210% 左右,Kafka 集群機(jī)器規(guī)模增長(zhǎng) 52%,接入數(shù)據(jù)量增長(zhǎng) 340%。
3. Kafka 部署架構(gòu)
針對(duì) Kafka 的部署架構(gòu),主要有兩種方案。方案一是使用大量物理機(jī)搭建一個(gè)超大規(guī)模的集群。方案二是以幾臺(tái)或幾十臺(tái)物理機(jī)為一個(gè)單位建構(gòu)若干小集群。這兩種方各自有其優(yōu)缺點(diǎn),方案一有點(diǎn)類似于在互聯(lián)網(wǎng)行業(yè)里的單體應(yīng)用,而方案二更類似于微服務(wù)架構(gòu)。實(shí)際兩種方案的選擇沒有絕對(duì)的好壞之分。
方案一有幾個(gè)優(yōu)點(diǎn):一是它的資源利用率較高,因?yàn)樗恍枰獙?duì)每一個(gè)小集群都預(yù)留一定的 buffer;二是當(dāng)集群規(guī)模比較大以后,它應(yīng)對(duì)數(shù)據(jù)業(yè)務(wù)方的業(yè)務(wù)流量突增能力比較強(qiáng),而不至于在業(yè)務(wù)流量突增時(shí),由于集群負(fù)載較高,進(jìn)而反壓到客戶端,影響用戶;三是用戶體驗(yàn)較好,對(duì)于業(yè)務(wù)團(tuán)隊(duì)只需維護(hù)一套集群的連接信息,無需根據(jù)業(yè)務(wù)場(chǎng)景自己維護(hù)、辨別、使用不同的集群連接信息。但同時(shí)方案一也帶來了一些問題:一是其運(yùn)維難度系數(shù)較高;二是一旦出現(xiàn)問題,故障影響面較廣;三是集群的資源隔離性較差。
方案二,這種小集群部署的優(yōu)點(diǎn):一是因?yàn)槊總€(gè)集群規(guī)模較小,運(yùn)維比較簡(jiǎn)單,但如果總體集群的總數(shù)達(dá)到數(shù)千個(gè),相應(yīng)的運(yùn)維投入也會(huì)隨之變高;二是當(dāng)集群出現(xiàn)故障時(shí),只會(huì)影響自己集群內(nèi)部,故障影響范圍較??;三是集群跟集群之間嚴(yán)格做了物理隔離,資源隔離性非常好。其缺點(diǎn),一是每一個(gè)集群都會(huì)需要一部分 buffer 來應(yīng)對(duì)業(yè)務(wù)流量的突增,資源利用率較低;此外在應(yīng)對(duì)用戶流量突增及用戶體驗(yàn)等方面的能力都會(huì)較差一些。
綜合考慮上述兩個(gè)方案的優(yōu)缺點(diǎn),在超大數(shù)據(jù)規(guī)模下,如果采用方案二,需要搭建和運(yùn)維的 Kafka 集群數(shù)量可能達(dá)到上千個(gè),單純靠人力運(yùn)維將會(huì)是一個(gè)較大的工作量,所以 vivo 采用的是方案一的部署架構(gòu),并針對(duì)其缺點(diǎn)進(jìn)行了改進(jìn)。
(1)引入資源組,實(shí)現(xiàn)集群內(nèi)節(jié)點(diǎn)邏輯隔離
首先針對(duì)大規(guī)模集群部署方案資源隔離性較差這一問題,通過在集群內(nèi)部引入資源組實(shí)現(xiàn)集群內(nèi)節(jié)點(diǎn)的邏輯隔離。資源組之間是邏輯隔離的,不會(huì)相互影響,從而實(shí)現(xiàn)了在同一個(gè)集群內(nèi)部的機(jī)器邏輯隔離。
(2)基于項(xiàng)目維度實(shí)現(xiàn)智能動(dòng)態(tài)限流
第二個(gè)問題是限流,限流本質(zhì)是通過犧牲一部分客戶端的可用性來保障服務(wù)端的可用性。Kafka 集群的限流有幾種方式,第一種是基于客戶端的(如基于 client ID),還有一種是基于用戶端的或稱基于項(xiàng)目的限流。vivo 公司內(nèi)部使用的是基于項(xiàng)目維度的限流。這種方式存在一些缺點(diǎn),首先業(yè)務(wù)受損嚴(yán)重,一旦出現(xiàn)了限流的情況,用戶的流量就進(jìn)不來,進(jìn)而導(dǎo)致用戶端被反壓,數(shù)據(jù)發(fā)送失敗或消費(fèi)延遲相關(guān)的問題;其次當(dāng)限速閾值設(shè)置不合理時(shí),會(huì)存在資源利用率較差和集群可用性風(fēng)險(xiǎn),限速閾值限制較高時(shí),集群的可用性得不到保障,限流閾值較低時(shí),集群資源利用率較低;第三用戶會(huì)經(jīng)常收到限流告警信息,用戶體驗(yàn)較差;第四用戶收到限流告警后需要運(yùn)維同學(xué)憑經(jīng)驗(yàn)綜合分析是否可以調(diào)整限速以便快速恢復(fù)業(yè)務(wù),運(yùn)維成本較高,因?yàn)橄蘖鏖撝挡恢С肿詣?dòng)進(jìn)行動(dòng)態(tài)調(diào)節(jié),業(yè)務(wù)會(huì)頻繁與 Kafka 組件的管理團(tuán)隊(duì)進(jìn)行溝通去調(diào)節(jié)這個(gè)閾值。
圖中左下方的案例示意了簡(jiǎn)單根據(jù)項(xiàng)目數(shù)量設(shè)定限流閾值時(shí)可能出現(xiàn)的一種情況。假設(shè)一臺(tái)單機(jī)的流量閾值是 100M/s,A、B 兩個(gè)項(xiàng)目均運(yùn)行在這臺(tái)單機(jī)上,對(duì)應(yīng)每一個(gè)項(xiàng)目分配到的限流閾值是 50M/s,當(dāng)流量超過限流值 50M/s 后,紅色陰影區(qū)域內(nèi)的流量都會(huì)被犧牲掉。但實(shí)際上多個(gè)項(xiàng)目之間存在流量的波動(dòng)周期的差距,因而不能采取一刀切的方式根據(jù)項(xiàng)目數(shù)量平均分配限流閾值。
針對(duì)這種情況,一種優(yōu)化思路是對(duì)在波峰期的項(xiàng)目 A,尋找其同一個(gè)資源組內(nèi)當(dāng)前流量值較低的項(xiàng)目 B,從項(xiàng)目 B 把流量借過來,動(dòng)態(tài)調(diào)高 A 項(xiàng)目的限流閾值,當(dāng) B 項(xiàng)目流量增長(zhǎng)后,再把流量還回去?;谶@樣的優(yōu)化思路,我們團(tuán)隊(duì)基于統(tǒng)一的監(jiān)控平臺(tái)、統(tǒng)一的指標(biāo)采集平臺(tái),以及統(tǒng)一的告警檢測(cè)平臺(tái)實(shí)現(xiàn)了智能動(dòng)態(tài)限流。
智能動(dòng)態(tài)限流需要解決限流粒度、限流閾值、可用性以及資源利用率這四個(gè)維度的平衡。這里我們引入了公司內(nèi)部提供的統(tǒng)一告警檢測(cè)平臺(tái)。在指標(biāo)采集過程中可能需要做一些降噪處理,解決數(shù)據(jù)的突刺現(xiàn)象,基于告警檢測(cè)平臺(tái)統(tǒng)一檢測(cè)的算法可以屏蔽掉異常告警,獲得精準(zhǔn)預(yù)警,然后基于此再去做動(dòng)態(tài)的限流調(diào)整。這套智能動(dòng)態(tài)限流方案使 vivo 公司內(nèi)部因?yàn)橄蘖鲗?dǎo)致業(yè)務(wù)受損的情況降低了 90%。
(3)流量均衡與資源均衡
Kafka 的架構(gòu)設(shè)計(jì)上分區(qū)與 broke 節(jié)點(diǎn)強(qiáng)綁定,默認(rèn)的分區(qū)分配算法不能很好的解決分區(qū)均衡性的問題,無法實(shí)現(xiàn)動(dòng)態(tài)調(diào)整。如上圖所示,Kafka 默認(rèn)的分區(qū)輪詢分散算法會(huì)產(chǎn)生兩種情況。第一種情況下,因?yàn)闊o法保證每一個(gè) topic 的分區(qū)數(shù)量都能與 broker 成正比,會(huì)出現(xiàn)一些 broker 上分配的分區(qū)數(shù)比較多,一些 broker 上分配的分區(qū)數(shù)比較少的情況。另外一種情況是,即使我們保證了在不同的 broker 上分區(qū)數(shù)量是盡可能一致的,但是由于 Kafka 的分區(qū)是有狀態(tài)的,所以說它會(huì)存在一些分區(qū)流量比較大,而另一些分區(qū)的流量比較小。這兩種情況都會(huì)使 broker 之間產(chǎn)生很大的流量差異。
我們?cè)谧鲞@種大規(guī)模的物理機(jī)集群部署時(shí),都會(huì)考慮通過一臺(tái)物理機(jī)掛載多塊磁盤從而提高物理機(jī)的 IO 效率。但 Kafka 的底層架構(gòu)設(shè)計(jì)上一個(gè)分區(qū)與 broker 的某一塊磁盤綁定,無法充分發(fā)揮多塊磁盤的 IO 效率。
如上圖所示,假設(shè)當(dāng)前有兩個(gè) topic,其中綠色 topic 的流量是 100MB/s,紅色 topic 的流量是 300MB/s。在 broker1 上掛載了 data1 到 data4 共 4 塊磁盤,但是當(dāng)前 Topic 分區(qū) P1-L 的數(shù)據(jù)只能寫入到磁盤 data1,這帶來一個(gè)致命的缺陷,當(dāng)磁盤 data1 出現(xiàn) IO 瓶頸時(shí),即使 data2 或者 data3 是空閑的,也沒辦法將數(shù)據(jù)轉(zhuǎn)寫到 data2 或者 data3 的磁盤上面去。這樣就導(dǎo)致當(dāng)某一塊盤上出現(xiàn)多個(gè)較大分區(qū)時(shí),它的磁盤 IO 瓶頸就會(huì)成為這一臺(tái)機(jī)器的性能瓶頸,沒辦法很好地利用起多塊盤的 IO。
基于該缺陷,我們團(tuán)隊(duì)也做了很多思考。首先,在當(dāng)前分區(qū)均衡算法上注入一些與主機(jī)相關(guān)的負(fù)載因子,使其去做更好的分區(qū)計(jì)劃。在第一期,我們注入了磁盤容量、CPU、流量等負(fù)載因子,使算法能生成更好的分區(qū)分散計(jì)劃。在第二期的分區(qū)均衡算法優(yōu)化上,注入了均衡性相關(guān)的參數(shù),如分區(qū)分散均衡、副本分散均衡等,使其能夠更好生成更加均衡的分區(qū)分散計(jì)劃。在跨機(jī)房方面我們也做了一些改進(jìn),實(shí)際情況中可能不需要所有的業(yè)務(wù)都實(shí)現(xiàn)跨機(jī)房容災(zāi),但是所有業(yè)務(wù)都必須實(shí)現(xiàn)跨交換機(jī)容災(zāi)。每個(gè)公司的機(jī)房建設(shè)不太一樣,我們公司的機(jī)房建設(shè)中,交換機(jī)是單上聯(lián)的,所以在交換機(jī)這個(gè)層面可能存在單點(diǎn)故障的風(fēng)險(xiǎn)。因此在后面交換機(jī)風(fēng)險(xiǎn)改進(jìn)方案里,我們也將交換機(jī)信息注入到分區(qū)均衡算法中,從而規(guī)避交換機(jī)的單點(diǎn)故障風(fēng)險(xiǎn)。未來我們也在思考跨機(jī)房實(shí)現(xiàn)分區(qū)分散,機(jī)房與機(jī)房之間的網(wǎng)絡(luò)延遲降低到可以接受的范圍之內(nèi)可輕松實(shí)現(xiàn)。
其實(shí) Kafka 核心架構(gòu)帶來的問題遠(yuǎn)不止上述提到的幾點(diǎn),尤其是在超大數(shù)據(jù)規(guī)模場(chǎng)景下,問題表現(xiàn)得尤為明顯。第一是 Kafka 資源利用率比較低,因?yàn)?Kafka 無法根據(jù)未來的流量增長(zhǎng)進(jìn)行預(yù)測(cè),所以也無法實(shí)現(xiàn)長(zhǎng)期的均衡。第二是 Kafka 故障恢復(fù)慢,因其分區(qū)數(shù)據(jù)是和磁盤綁定的,當(dāng)進(jìn)行數(shù)據(jù)遷移時(shí),遷移周期會(huì)比較長(zhǎng),尤其當(dāng)一塊磁盤上有幾 T 數(shù)據(jù)或一臺(tái) broker 上有幾十 T數(shù)據(jù)時(shí),磁盤故障需要做踢盤或 broker 節(jié)點(diǎn)故障需要做下線時(shí),需要遷移幾 T 或幾十 T 數(shù)據(jù)。數(shù)據(jù)遷移過程中還需要考慮不能影響實(shí)時(shí)業(yè)務(wù)數(shù)據(jù)的寫入,遷移周期一般都是周級(jí)。第三是 Kafka 故障率高,均衡時(shí)會(huì)做數(shù)據(jù)的拷貝、消費(fèi)延遲時(shí)會(huì)讀磁盤數(shù)據(jù)導(dǎo)致磁盤 IO 受到影響,一旦出現(xiàn)這個(gè)問題,對(duì)實(shí)時(shí)數(shù)據(jù)的寫入也會(huì)存在影響,所以它的故障率會(huì)比較高。第四是無法快速響應(yīng)業(yè)務(wù)增長(zhǎng),當(dāng)集群擴(kuò)容后需要先對(duì)分區(qū)做一次均衡,然后做流量歷史數(shù)據(jù)的遷移,全部遷移完后才可以將實(shí)時(shí)數(shù)據(jù)寫入到擴(kuò)容機(jī)器上,整個(gè)擴(kuò)容的周期較長(zhǎng)。一般對(duì)于 Kafka 集群的擴(kuò)容是以天或者以周為單位進(jìn)行的。
基于以上所有的缺陷,我們發(fā)現(xiàn)核心問題在于 Kafka 數(shù)據(jù)存儲(chǔ)架構(gòu)設(shè)計(jì)上,無法通過擴(kuò)展能力的建設(shè)解決上述缺陷。Kafka 的架構(gòu)設(shè)計(jì)沒辦法做到存算分離、分層存儲(chǔ)、分散存儲(chǔ)等。所以我們考慮要對(duì)整個(gè)分布式消息中間件做引擎的升級(jí),解決方案有兩種,第一是基于 Kafka 的原有架構(gòu)進(jìn)行改造,第二是引入下一代的云原生分布式消息中間件 Pulsar。
二、Pulsar 核心架構(gòu)升級(jí)
Pulsar 是基于云原生理念設(shè)計(jì)的分布式消息流組件,它在存儲(chǔ)層和計(jì)算層實(shí)現(xiàn)了存算分離,并且其同一分區(qū)的數(shù)據(jù)可以分散成多個(gè) segment,每個(gè) segment 可以落到不同的 bookie 存儲(chǔ)節(jié)點(diǎn)上,實(shí)現(xiàn)了在存儲(chǔ)節(jié)點(diǎn)上的分散,也可以實(shí)現(xiàn)在磁盤之間的分散。Pulsar 的核心架構(gòu)具有以下幾個(gè)核心優(yōu)勢(shì):
- 存儲(chǔ)與計(jì)算分離。
- 存儲(chǔ)、計(jì)算獨(dú)立擴(kuò)展。
- 秒級(jí)擴(kuò)縮容。
- 秒級(jí)的故障恢復(fù)。
- 屏蔽硬件故障。
Pulsar 支持在硬件上面的秒級(jí)恢復(fù)。如圖所示,左邊是 Kafka 的架構(gòu),當(dāng)磁盤發(fā)生故障后,必須去副本所在的 broker 節(jié)點(diǎn)把數(shù)據(jù)先同步一份,之后才可以把實(shí)時(shí)流量數(shù)據(jù)寫到我們的 broker 磁盤上。但是數(shù)據(jù)同步的周期性較長(zhǎng),可能要一天或者更長(zhǎng)的時(shí)間,在這段時(shí)間之內(nèi),如果分區(qū)的副本數(shù)設(shè)置為 2,分區(qū)都處于單副本運(yùn)行的高風(fēng)險(xiǎn)狀態(tài)。而 Pulsar 可以實(shí)現(xiàn)秒級(jí)的恢復(fù),因?yàn)樗恍枰プ鰵v史數(shù)據(jù)的同步,分區(qū)流量可以秒級(jí)的轉(zhuǎn)移到其他磁盤或其他的 broker 上。Pulsar 后臺(tái)有一個(gè)缺副本的發(fā)現(xiàn)機(jī)制,補(bǔ)齊歷史數(shù)據(jù)。在實(shí)時(shí)場(chǎng)景下,我們更關(guān)注對(duì)實(shí)時(shí)寫入的數(shù)據(jù)做冗余的高可用保障,反而對(duì)于歷史數(shù)據(jù)同步性的要求不高。
Pulsar 具備秒級(jí)擴(kuò)縮容的能力,這主要基于它存儲(chǔ)與計(jì)算分離的架構(gòu)。因其存儲(chǔ)計(jì)算分離,它的 broker 和 bookie 也是分離的。一個(gè)無狀態(tài)的服務(wù)實(shí)現(xiàn)秒級(jí)的擴(kuò)縮容是很簡(jiǎn)單的,基于 K8S 或者 docker 來講的話,只需要彈一個(gè) Pod,然后去拉取一個(gè)鏡像,重啟后就可以完成秒級(jí)的彈性伸縮。Pulsar 在 broker 層是無狀態(tài)的設(shè)計(jì),使其它天然具備了秒級(jí)擴(kuò)縮容能力。在 bookie 層,可以將其看作存儲(chǔ)層,它也可以做到秒級(jí)的擴(kuò)縮容,只要擴(kuò)容 bookie 節(jié)點(diǎn)被 broker 感知到以后,可以實(shí)時(shí)地將 broker 的流量寫到 bookie 節(jié)點(diǎn)上進(jìn)行持久化的存儲(chǔ)。
Pulsar 核心架構(gòu)優(yōu)勢(shì)還體現(xiàn)在客戶端內(nèi)存分配上。在 Kafka 的架構(gòu)下,尤其是在指定 key 的場(chǎng)景下,如果 broker 節(jié)點(diǎn)出現(xiàn)宕機(jī)或者響應(yīng)緩慢的情況,就會(huì)反壓客戶端,導(dǎo)致客戶端 buffer pool 被故障分區(qū)的數(shù)據(jù)打滿,進(jìn)而導(dǎo)致雪崩的現(xiàn)象。因?yàn)橐粋€(gè)分區(qū)不可用,導(dǎo)致整個(gè) topic 的所有分區(qū)都不可用甚至當(dāng)前 producer 涉及的所有 topic 的所有分區(qū)都不可用。左下方是我們公司內(nèi)部一次故障時(shí)的流量監(jiān)控曲線,可以看到,Kafka 單個(gè) broker 節(jié)點(diǎn)一場(chǎng)后,整個(gè)資源組里所有 topic 的流量都無法寫入,就是因?yàn)楣收瞎?jié)點(diǎn)直接把客戶端內(nèi)存占滿后,正常分區(qū)的數(shù)據(jù)沒辦法分配到內(nèi)存,無法寫入到服務(wù)端。對(duì)于這個(gè)問題,Pulsar 做了架構(gòu)上的改造。客戶端內(nèi)存的隔離粒度做到了分區(qū)級(jí),當(dāng)右上圖 broker2 出了問題,即使分區(qū)的 deque 被打滿以后,也不會(huì)去占用整個(gè)客戶端內(nèi)存,消息還是能通過其他可用分區(qū)發(fā)送出去。右下方圖展示了我們故障演練的情況,它可以秒級(jí)恢復(fù)到其他 broker 節(jié)點(diǎn)上。
Pulsar 和 Kafka 的性能對(duì)比可以參見下圖。
三、高可用保障及可觀測(cè)
高可用保障是我們的生命線,沒有高可用,其他一切工作都是沒有意義的。
高可用保障主要圍繞故障展開,包括事前預(yù)防故障的發(fā)生、事后快速恢復(fù),以及故障解決后應(yīng)該怎樣復(fù)盤并提出改進(jìn)措施。我們?cè)谑虑埃瑫?huì)基于對(duì)技術(shù)架構(gòu)的理解做故障演練和測(cè)試,在流程規(guī)范和平臺(tái)工具方面進(jìn)行保障。事中最核心的是整個(gè)監(jiān)控告警體系,在此基礎(chǔ)上進(jìn)行質(zhì)量運(yùn)營(yíng),及時(shí)發(fā)現(xiàn)、響應(yīng),最終支撐組件在超大數(shù)據(jù)規(guī)模下的高可用。
我們的監(jiān)控告警體系可以分為多個(gè)維度。在基礎(chǔ)設(shè)施層,實(shí)現(xiàn)了對(duì)機(jī)房、網(wǎng)絡(luò)、交換機(jī)的監(jiān)控;在主機(jī)層,實(shí)現(xiàn)了對(duì) CPU、內(nèi)存、磁盤流量相關(guān)的監(jiān)控;在服務(wù)層,尤其是在 Kafka 的服務(wù)層,會(huì)對(duì) GC、warning 日志或 error 日志進(jìn)行監(jiān)控告警;在用戶層,支持限流告警、延遲告警以及流量突增的告警。以上都是為了在故障發(fā)生前一步告警,以便及時(shí)介入人工干預(yù),避免故障發(fā)生。所有告警指標(biāo)的采集都由統(tǒng)一檢測(cè)平臺(tái),經(jīng)過降噪,統(tǒng)一發(fā)出異常告警,觸達(dá)我們的用戶、運(yùn)維以及管理人員。在進(jìn)行監(jiān)控告警體系建設(shè)時(shí),比起頻繁告警,我們更重視告警的精準(zhǔn)度,尤其是在有限的人力運(yùn)維情況下,太多的告警會(huì)導(dǎo)致運(yùn)維人員對(duì)告警的敏感度下降,忽視關(guān)鍵告警,最終導(dǎo)致故障的發(fā)生。
因?yàn)槿司哂兄饔^能動(dòng)性,人為因素是導(dǎo)致故障的重要誘因之一,所以我們需要一套貫穿于整個(gè)事前事中以及事后的規(guī)范體系來規(guī)范人的行為。包括事前對(duì)代碼管理、方案和代碼的評(píng)審、發(fā)布和變更、變更灰度優(yōu)先級(jí)、值班等的規(guī)范,事中對(duì)故障處理的規(guī)范、預(yù)案執(zhí)行的規(guī)范、日常運(yùn)維的規(guī)范,事后故障的管理規(guī)范,以及故障的復(fù)盤規(guī)范等,通過一套全生命周期的規(guī)范來盡可能規(guī)避人為因素導(dǎo)致的故障。
Pulsar 作為新一代云原生分布式消息中間件,架構(gòu)設(shè)計(jì)非常優(yōu)秀,但是作為新興組件缺乏長(zhǎng)期超大規(guī)模數(shù)據(jù)處理的驗(yàn)證,在穩(wěn)定性上也存在較多問題?;谖覀兤脚_(tái)的高可用體系,以及監(jiān)控告警體系的實(shí)踐,經(jīng)過故障演練和自測(cè),我們?cè)诮鼉赡觊g解決了 Pulsar 27 個(gè)嚴(yán)重影響穩(wěn)定性的問題,19 個(gè)重要問題,44 個(gè)一般問題。目前在達(dá)到 2 萬(wàn)億日均處理消息量的情況下,我們做到了全年無故障。
可觀測(cè)對(duì)于用戶來講,可能關(guān)注的是 topic 的流量指標(biāo),尤其是 top 級(jí)別的流量指標(biāo),根據(jù)觀測(cè)結(jié)果決定是否需要對(duì)某一些 topic 做治理,或者判斷該 topic 消耗的成本是不是與它所帶來的收益正相關(guān)。此外我們還會(huì)關(guān)注消費(fèi)延遲指標(biāo)。我們的可觀測(cè)平臺(tái),能夠?qū)崟r(shí)定位到用戶某一臺(tái) IP 節(jié)點(diǎn)上的機(jī)器出現(xiàn)消費(fèi)延遲的情況,方便我們?cè)跀?shù)據(jù)消費(fèi)延遲的時(shí)候能夠快速定位到問題。
我們的告警實(shí)現(xiàn)了從數(shù)據(jù)接入,到檢測(cè)配置,再到告警配置以及告警處置四個(gè)方面的閉環(huán),相關(guān)的配置都可以通過平臺(tái)進(jìn)行配置操作,對(duì)告警的處置、告警的回調(diào)、告警的詳情都可以通過可觀測(cè)的告警平臺(tái)進(jìn)行查看。
最后對(duì)于運(yùn)維管理人員而言,我們更關(guān)注的是當(dāng)遇到故障后如何快速恢復(fù),以及是否能通過一些日常巡檢來發(fā)現(xiàn)當(dāng)前系統(tǒng)存在的異常。因此我們?cè)谶\(yùn)維管理方面,也實(shí)現(xiàn)了可觀測(cè),包括對(duì) topic 的流量監(jiān)控,對(duì)整個(gè)資源組的 GC 監(jiān)控,以及對(duì)延遲的監(jiān)控等。
四、vivo 架構(gòu)未來規(guī)劃
最后談一下 Pulsar 未來規(guī)劃。Pulsar 作為下一代云原生的分布式消息中間件一定會(huì)成為未來的主流。因此我們對(duì)其分層存儲(chǔ)以及函數(shù)式計(jì)算、全鏈路監(jiān)控會(huì)重點(diǎn)規(guī)劃。另外如何應(yīng)用 Pulsar SQL,以及 Pulsar function 使其更好地賦能業(yè)務(wù)也是我們未來需要去考慮的一些點(diǎn)。最后,關(guān)于 Pulsar 容器化的問題我們也有一定的思考,前文在介紹 Pulsar 部署架構(gòu)的部分提到了大量小集群運(yùn)維,采用純?nèi)肆Φ倪\(yùn)維不太現(xiàn)實(shí),如果說未來能夠?qū)崿F(xiàn)容器化,由容器化來幫助我們做集群管理,就能大量節(jié)省運(yùn)維人力成本。