分享概要
一、背景
二、設計思路
三、雙活整體架構
四、具體改造方案
五、上線環節
六、項目成果
七、帶來的新問題及後續
知易行難,雙活過程中遇到了非常多的問題,但是回過頭看很難完美表述出來,之是以這麼久才行文也是這個原因,總是希望可以盡可能複現當時的思考、問題細節及解決方案,但是寫出來才發現能給出的都是多次打磨、摸索之後的我們認為偏合理的方案;不過換個角度看,給大家展示出來一個正确答案,是否有更積極的參考價值呢?
以及,涉及到容器、釋出平台、底層網絡運維、監控等元件的内容,限于視野及技術能力并未包含在内,僅聚焦在業務團隊及中間件元件的設計及改造上。
一、背景
2022年,基于對穩定性的焦慮和思考,交易平台關聯中間件平台啟動過異地多活項目的探索,雖然完成了核心應用及基礎元件的改造,但在疫情&降本增效的影響下并未真正投産,同時也缺乏充分的測試以及線上流量的大規模驗證;後續在不斷的業務疊代中,相關設計及代碼被沖擊得面目全非,相關的多活自動化測試case也并沒有沉澱下來。
随着近期外部友商時有嚴重故障出現,比如:
以上林林總總出現的故障都給我們敲響了警鐘,必須建設快速恢複的能力。出現問題幾乎不可避免,但如果能控制影響範圍、縮短影響時間,也就能把損失降到最低。
我經曆過的公司,做交易的和做中間件的,往往是最容易焦慮,也最容易心态失衡的兩撥技術人;一方面所有問題都會暴露在C端使用者面前,影響範圍大且不像toB/toM的場景,避開高峰期甚至有可能無人知曉;另一方面流量高,壓力大,容易面臨突發流量及突發事件,穩定性這根弦需要始終繃緊;是以往往是面向穩定性(的焦慮)設計,當然熬過去成長也最快。
回到我們的現狀,得物目前的交易應用及中間件基礎元件都是基于某雲部署,且前期為了降低跨機房調用産生的網絡損耗,較多應用都綁定了存儲元件(db/redis/hbase)及核心依賴下遊的所在可用區,對此,為了避免在極端情況下,得物的交易主鍊路出現長時間不可用的情況,團隊決定提前預防,啟動同城雙活項目。
為了避免在極端情況下,得物的交易主鍊路出現長時間不可用的情況,團隊決定啟動同城雙活項目,目标是快速建設流量動态切換能力及快速恢複能力,同時降低改造難度、減少改造工作量,不增加大量額外成本。團隊讨論決策繞過之前最複雜也最容易出問題的資料同步(db雙向同步、redis雙向同步等),同時也不需要在流量切換時做db禁寫,整體具有比較大的可操作可實施性。
多說一句,同城雙活也有做資料雙向同步的case,當然更徹底--每個機房都有全量的資料及應用,某個機房出問題 可以完全自閉環承接流量,不過帶來的複雜度上升、成本上升也會比較明顯,是以這次并沒有選擇這條路。換句話說,個人更傾向于小成本低風險快速落地,實作從0到1的功能建設,而不是大而全的方案,萬一期間遇到問題隻能徒呼奈何。當然在現階段,通過建設相對低風險低投入的同城雙活,積累更多基礎能力的同時鍛煉團隊,選擇最合适當下的方案,解決目前排在第一位的問題,怎麼想都覺得還是一件挺劃算的事兒。
畫一幅簡圖來區分下我們這次同城雙活的方案和業界異地雙活方案的差異。
1.異地雙活
主要特點:
- 存儲相關有兩份,雙機房内各自讀寫,雙向同步
- 資料的循環指派需要重點考慮如何處理
- 資料間的同步延遲問題會比較明顯,不過各自機房内基本上可自閉環調用
- 對于使用者、商家資産的處理比較複雜,比如使用者券、賣家庫存等,一般需要考慮在某個機房維護(gzone),避免資料同步問題帶來的超賣、超用
- 切流時需要做目标機房的局部資料禁寫,避免髒資料産生
2.同城雙活
特點:
- 隻有一份資料源,不需要考慮資料同步的延遲問題及切流時的禁寫邏輯,不過若資料所在機房出問題,另一個機房無法正常承接流量(隻能承接部分兜底流量,如cdn、緩存等有兜底資料的場景)
- 不需要考慮具備中心節點性質的資料問題,如使用者券、庫存等
- 跨機房通路較多,尤其是資料層面的讀寫,可能會造成RT的大幅上漲
不管是同城還是異地、雙活還是多活(雙活隻是多活裡最簡單的場景,雙活到三活難度飙升範圍應該不亞于<羊了個羊>裡第一關和第二關的難度),都是為了以下目标:
- 提高可靠性:通過在不同的實體位置部署服務,減少單點故障的風險。即使一個機房發生故障,其他機房也可以接管服務,確定業務連續性。
- 負載均衡:可以靈活配置設定使用者請求流量,避免單個機房過載,尤其随着業務規模的擴大單個雲廠商的機房已經無力提供更多資源的情況下。
- 災難恢複:通過流量的排程切換來快速恢複某個機房的故障問題,減少業務中斷時間。
- 雲成本:在技術成熟度較高的前提下,做同雲、跨雲 甚至雲+自建IDC機房之間的多活,一方面可以降低對某個雲廠商的依賴進而擷取一定的議價權;另一方面多活本身在提高資源使用率方面可以有更多可能性。
- 提高服務品質:這點尤其表現在異地多活場景,通過在多個中心之間配置設定流量,可以減少網絡延遲,提供更快的響應時間和更高的服務品質。
二、設計思路
一句話描述:在雲機房的多個可用區(即多個實體機房)中構造應用層面的雙叢集部署,配合目前已經在交易鍊路大規模上線的藍綠釋出,完成流量的動态切換(含HTTP、RPC、DMQ[rocketmq/kafka])。而存儲(redis/db)還是在單機房(但是可以跨機房部署),降低方案及實作的複雜度。
三、雙活整體架構
可以看到,整體在架構層面分為四層:
- 接入層:DNS 域名解析+ SLB主備 + DLB+DAG多機房部署,保障接入層高可用。其中在DAG中實作了根據使用者ID、流量比例等控制藍綠流量的政策。
- 應用層:應用通過改造,劃分為邏輯藍綠叢集,通過藍綠同調的粘性屏蔽跨區調用。
- 中間件層:多個中間件元件有各自不同的跨AZ部署政策、資料同步、主動切換政策,下面會詳述。
- 資料層:資料層保持一份資料,通過自動/手動主從切換,跨區部署等技術手段,保障機房級别故障下服務可用,包含DB、Redis、Hbase等。
四、具體改造方案
本次雙活涉及到三個主要部分,分别是:交易應用側雙活改造、交易依賴方應用雙活改造、中間件&基礎元件改造。下面分别介紹:
1.交易應用側雙活改造
1)項目範圍
交易側預設所有服務均參與同城雙活改造,一方面内部應用之間的調用關系複雜,區分處理梳理工作量極高;另一方面快速的業務疊代也會改變互相之間的依賴關系,維護這套邏輯成本太高;以及,内部強弱依賴本身也在動态變化,讓團隊的同學不斷的識别哪些應該雙活、哪些應該單點,溝通和執行成本反而更高。
2)業務改造思路及方案
實際業務場景中複雜的鍊路拓撲最終可以抽象為如下典型的、原子的鍊路拓撲(A-B-C)的疊加、組合。
A、C服務參與雙活,需要跨可用區部署。B服務不參與雙活,不需要跨可用區部署。
A、B、C服務都需要識别流量染色、服從流量排程。
- 相關服務Owner各自将服務中內建的統一基礎架構更新到指定版本,接入無侵入、零配置、開箱即用的藍綠釋出能力元件全家桶。保證基于藍綠釋出的運作時流量排程能力被完整內建。上述簡圖中A、B、C服務需要進行該步驟。
- 相關服務Owner各自在釋出平台界面白屏化遷移釋出模式。釋出模式遷移到藍綠釋出時,釋出平台自動将服務Pod進行跨可用區部署,并在Pod中注入支撐流量排程的程序級元資訊。藍綠釋出能力元件在上遊調用方LoadBalance時介入進行流量染色、流量排程。上述簡圖中A、C服務需要進行該步驟。
完成上述改造後,雙活鍊路上的流量呈現就近調用、可用區封閉的特點,即:流量染色後,後續鍊路上的每一跳調用都會優先向下遊服務叢集中與流量同色(同可用區)的執行個體發起調用。
2.交易依賴方應用雙活改造
僅僅依靠交易側應用,無法完成所有的P0鍊路,如下單時依賴供應鍊側時效。強依賴的外域服務同樣納入了同城雙活改造範圍。其改造點基本一緻,不再贅述。
3.中間件&基礎元件
1)識别機器資源可用區
項目初期,我們發現容器POD和ECS缺少可用區辨別,導緻無法區分對應的資源歸屬。于是我們配合運維組和監控組的同僚制定了一份規範。在環境變量裡給機器都打上對應的标記,同時這也是監控和日志能透出機房标記的基石。
2)中間件RTO
同城雙活要求中間件在單個可用區出問題的時候,仍能對外提供服務。其設計目标的RTO為以下:
3)主要元件雙活改造方案
①DLB - 自研流量網關
- DLB是無狀态元件,在兩個可用區對等部署。
- 當其中一個可用區故障時,在SLB的endpoints上故障節點會被剔除,流量會打到正常的節點,實作故障快速恢複的目标。預計秒級完成。
②彩虹橋 - 自研分布式關系資料庫代理
彩虹橋目前不具備自動流量切換能力,一方面自動切換過于複雜,另一方面也容易帶來更多的風險,以及也依賴DB層面的主備切換,是以走手動切換,預計分鐘級完成。
目前流量99%走A區叢集、1%的流量走B區叢集,當A區發生可用區故障時,可手動把流量全部排程至B區叢集,同時需要DB層完成主備切換(a->b)。
③DMQ
通過Broker分片級别打散到不同的可用區形成一套完整的叢集。
當可用區故障時,叢集可用分片會減少一半,叢集整體可用。
DMQ的改造經過了多次試錯,最開始通過在消費端建立多個consumer group的方式實作,但需要業務側配合多次更新處理,且會導緻消費端存在雙倍的consumer group,後面才決定将主要改造工作放在rocketmq broker内部。簡要介紹如下:
- 藍綠屬性
BROKER中的隊列設定成偶數,并且>=2。我們把前一半隊列視為邏輯上的藍色隊列,後一半隊列視為綠色隊列(這裡也可以看到,雙活裡的很多處理邏輯都是非此即彼,但是如果到多活,複雜度就會更高)。
- 生産者
在進行隊列選擇時,根據叢集環境藍綠顔色進行分組選擇:
- 藍叢集的消息會被投遞的broker的前一半隊列中
- 綠叢集的消息會被投遞到broker的後一半隊列中
在每種選擇邏輯内部是按照輪循的方式進行選擇,不破壞生産者本身支援的容錯邏輯。
- 消費者
消費者也是類似。藍色消費者消費藍色隊列的消息。綠色消費者消費綠色隊列的消息。
④Kafka
由于ZK的ZAB協定要求保證 Math.floor(n/2)+1 奇數個節點存活才能選出主節點,是以 ZK 需要進行3個可用區部署,上面的nameserver類似。分散在3個可用區中,A:B:C 節點數 = 2N:2N:1,確定始終是奇數個叢集節點。
Broker 在兩個可用區對等部署,分區的主從跨區部署。當單個可用區故障時,分區leader切換。
⑤ES
ES多可用區部署,需要區分資料節點和master節點。
- 資料節點:需要保持各個可用區之間節點對等,以保證資料的平衡;使用分區感應把主副分片隔開,保持在不同可用區内。
- master節點:部署在至少三個可用區,以保證任何一個可用區挂了,都不影響master的選舉。
⑥注冊中心
PS:自研分布式注冊中心,基于raft協定實作系統可用性、資料一緻性。承擔得物全站RPC服務釋出/訂閱職責。
- 代理節點多分區部署,保障多可用區雙活
- Sylas叢集Raft節點3個分區部署,保障多可用區雙活
4)流量配置設定政策
①RPC流量
雙活的RPC的入口流量在DAG上進行調整,DAG會盡量根據使用者ID進行流量配置設定。
- 每個應用會在請求上下文中附上目前的藍綠辨別;
- 如果某個應用沒有納入雙活範疇,這裡的藍綠辨別會丢失,此時有兩種政策:
a. 随機配置設定,不過會破壞鍊路的純潔性;
b. 根據userID再算一次,不過需要增加一次對ark配置的處理。
②MQ流量比例
因為藍綠叢集的生産者和消費者對隊列進行了綁定。是以隻要調整藍綠生産者的消息比例就可以調整整個MQ的消費流量比例。而藍綠生産者的消息比例一般由RPC流量決定。是以調整RPC的流量比例,MQ的流量比例也會得到相應的調整。不過會有一定的滞後(5-10s)。
五、上線環節
1.前期準備階段
整體思路确定:
- 基于目前的藍綠釋出做雙活,每次的藍綠釋出過程就是一次雙活切流演練,避免長久不使用,需要用的時候手忙腳亂或者年久失修
- 服務層做雙活部署,資料層不做大的改造,DB和Redis通過自身的主從切換實作高可用,從節點分布在不同的可用區
- 交易域内所有服務+核心鍊路相關外域服務做雙活改造
梳理所有業務場景、MQ情況、容器部署現狀、資料庫&緩存主從節點可用區現狀:
- 交易域所有服務&以及核心業務場景強依賴的外部服務、強依賴的具體業務場景、可否降級&有無兜底
- MQ使用情況:DMQ還是Kafka還是其他、是否需要保證消息的順序性
- 所有服務目前機器所在可用區、是否綁定固定可用區
- 交易域所有資料庫、Redis對應的主節點和從節點分别所在可用區情況
- 依賴zookeeper的job情況
評估改動範圍:
- 上下遊非交易域溝通确認(必須納入改造範圍的服務、可以不用雙活改造的服務必須要有兜底)
- 雙活涉及到的服務jar更新、未接入藍綠釋出的接入藍綠釋出
- 跨區調用情況下RT上漲明顯的接口針對性優化
部分業務場景是否需要接入自建Redis的就近讀改造:
- 運維側提供自建Redis的就近讀方案,但是對于資料一緻性方面有所犧牲,各方根據實際業務場景和接口RT情況綜合評估是否需要接入
2.開發&驗證階段
1)服務jar更新:支援雙活藍綠切流、支援MQ藍綠發送&消費
2)雙活藍綠染色測試環境搭建、測試流程改善:
- 環境本身的搭建:服務藍綠叢集拆分、綁定可用區、容器藍綠叢集機器比例配置
- 雙活藍綠染色環境代碼版本校驗、代碼準入規則、分支自動合并規則、測試流程流轉等
- 将雙活藍綠染色環境定為測試二輪round2環境,在日常疊代中常态化回歸驗證雙活流程
3)雙活藍綠染色測試環境回歸:
- 正常業務流程回歸
- 測試環境藍綠切流回歸
- 測試環境MQ生産&消費切流回歸
- 核心業務接口RT情況記錄對比、優化意見
4)雙活染色環境全局通道打開情況下藍綠釋出通道切流回歸:
- 驗證通道優先級:釋出通道優先級 > 全局通道
5)預發環境叢集拆藍綠
- 此刻預發環境等于已經實際上完成了雙活改造
6)預發環境驗證&RT問題重點關注
7)線上所有雙活改造服務單獨拆一台機器到B區觀察&驗證RT上漲問題:
- 交易平台絕大部分服務之前都是綁定可用區A區,每個服務單獨部署一台機器到B區,觀察接口RT情況
8)DMQ更新藍綠2.0支援按照藍綠标消費
3.線上準備&上線階段
1)日志平台、監控平台、trace鍊路、容器更新支援藍綠标
2)生産環境DMQ切換為藍綠2.0支援按照雙活藍綠标消費
3)資料庫&Redis主節點切換,保證主從節點隻在A區或者B區
- 大部分在a、b這兩個區,也有例外。核心是主節點一定要在這兩個區
4)線上服務拆分藍綠叢集(手動),項目正式上線,回歸驗證&RT問題關注
5)綠叢集(A區)擴容至100%機器,藍叢集(B區)維持50%機器,灰階觀察5天
6)線上RT上漲接口技術專項優化
7)釋出平台雙活保障疊代更新
- 支援新增服務一鍵加入雙活藍綠叢集
- 雙活藍綠叢集支援按區批量擴容能力(單機房故障情況下,快速拉起存活區的服務)
8)容器平台支援容器管控多可用區部署
六、項目成果
2023年12月14日,籌備近100天的交易鍊路同城雙活完成上線,經過5天(12.14-12.18)的觀察及聖誕前高流量(DLB流量達到雙十一的77.8%)的驗證,确認無明顯異常,之後線上叢集完成縮容。部分場景的RT有一定比例的上漲(資料層面隻做了跨可用區容災,但是并沒有實作就近通路,是以藍叢集的所有資料層面調用都需要跨可用區),已啟動技術小項目推動優化中。
從實際效果上看,經過12.22的大版本釋出過程中的跨機房切流,交易鍊路已經具備跨機房流量排程的能力,如下:
1.流量表現
(A區 - 綠叢集,B區 - 藍叢集)
- 兩個可用區的叢集流量達到了50:50。不過rocketmq 由于存在少量上下遊應用并未進行多活改造,還有較小流量未嚴格分布
- 核心名額 qps/rt/錯誤率
- 核心基礎元件通路情況
由于所有資料存儲(db、redis、hbase)均在A區,故B區的 rt 有一定上漲,整體看上浮大概 7-8ms( 存在一次請求 查詢多次資料的場景),還在持續推動優化。
2.成本情況
因A區原有雲資源均為包年包月模式,停止使用依然會有費用産生;同時在B區部署服務穩定性支撐50%流量之前,存在5天的并行期(A區100%資源、B區50%資源,共150%),期間共産少量成本。
灰階并行期結束後,A區資源釋放掉50%,整體成本回歸原有平均線,無額外成本産生。
七、帶來的新問題及後續
1. 藍綠釋出中,如果下遊接入了雙活但沒有進入釋出通道,消費流量會傾斜,比如在上遊切換流量過程中,RPC或MQ會優先本可用區調用,也就是另一個可用區流量比例會受影響;需要關注每個可用區中備援的容量評估是否可以支撐全量流量。
2. RT變化,對于下遊未加入雙活、或者某些存儲/緩存中間件,如DB/Hbase/Redis未開啟就近讀取,B機房的RT會普遍高5-8ms。已在逐漸投入優化。
3. 容器管控作為基礎設施,在出現機房級故障的時候需要保證正常運作,能夠順利完成擴縮容操作,即容器管控面的多可用區部署,這塊目前還在建設中。
4. 機房級故障情況下,單機房批量擴容快速拉起,是否有足夠的可用資源(尤其是大促期間,雲廠商本身資源就吃緊)。
5. 多個大域之間的雙活關聯問題,比如交易和搜推:
- 兩個大域雙活切流是否需要關聯(關聯:影響範圍被放大,且搜推側擴容不易;不關聯:各域雙活流量非常割裂)
- 兩個大域之間的是否識别相同的藍綠标(各大域内部自閉環保證同區通路or大域之間也需要保證)
6. 如何線上上無損情況下進行一次貼近實際的演練。
以上問題都是在雙活之後帶來的新挑戰,也都在不斷思考及投入解決。
不管做什麼,不管怎麼做,人生總會有新的問題出現,不是麼?Keep a long-term view lol...
作者丨Alan 英傑 Matt 羊羽
來源丨公衆号:得物技術(ID:gh_13ba5621e65c)
dbaplus社群歡迎廣大技術人員投稿,投稿郵箱:[email protected]
活動推薦
2024 XCOPS智能運維管理人年會·廣州站将于5月24日舉辦,深究大模型、AI Agent等新興技術如何落地于運維領域,賦能企業智能運維水準提升,建構全面運維自治能力!
會議詳情:2024 XCOPS智能運維管理人年會-廣州站