鬥魚直播雲原生實踐之註冊中心篇

騰訊雲原生發表於2021-09-29

作者

孔令圳,鬥魚首席架構師,全面負責鬥魚全站技術架構體系規劃和建設,10 餘年中大型網際網路產品架構經驗,擅長高併發、高可用場景下的架構與方案設計。

於競,鬥魚技術保障運維專家,負責鬥魚高可用基礎架構建設,擅長註冊中心、監控體系等技術領域,同時也是鬥魚多活基礎保障負責人。

唐聰,騰訊雲資深工程師,極客時間專欄《etcd 實戰課》作者,etcd 活躍貢獻者,主要負責騰訊雲大規模 k8s/etcd 平臺、有狀態服務容器化、在離線混部等產品研發設計工作。

陳鵬,騰訊雲容器服務產品架構師,多年專注雲原生領域,幫助了大量使用者雲原生容器化改造和生產落地,擁有豐富的一線實踐經驗,也發表了海量的雲原生技術文章。

業務背景和痛點

鬥魚直播作為業界領先的遊戲直播平臺,每天為數以億計的網際網路使用者提供優質的遊戲直播觀看、互動和娛樂等服務。

隨著近年直播市場的火熱,鬥魚直播平臺作為業內口碑和體驗俱佳的網際網路公司,使用者量也出現井噴式增長。海量使用者給平臺帶來的穩定性技術挑戰也越發強烈,鬥魚的老架構如下圖所示,無論是業務支撐還是架構設計,均存在一定的風險和隱患。

鬥魚老架構

圖一 鬥魚老架構

為了給使用者帶來更好的可用性體驗,鬥魚急需解決單一資料中心的問題,將老架構從單資料中心升級到多資料中心。

多資料中心挑戰

在實現單活升級為多活的過程中,為了確保無故障的遷移升級,我們面臨一系列挑戰,比如:

有狀態服務 etcd、zookeeper 等如何多資料中心同步?
應用彼此之間存在 1 個複雜的樹狀或網狀依賴關係,應該從哪裡開始遷移?
按什麼維度來劃分目標的邊界,怎麼避免業務焊死在一起,造成無從下手的局面?
如果遷移後出現問題,如何快速恢復,並且不牽連已遷移成功的業務?
因單活升級到多活的過程中,涉及系統眾多,本文將是鬥魚直播多活改造系列的第一篇,只聚焦於註冊中心模組,因此我們先和你介紹下注冊中心背後的 etcd 和 zookeeper。

zk/etcd 承擔的角色

dubbo 通過註冊中心來解決大規模叢集下的服務註冊與發現問題,以下是註冊中心架構圖:

dubbo 預設支援 zookeeper 註冊中心,雖然新版也有 etcd 實現,但該實現尚缺乏大規模投產的先例,Java 技術棧採用 etcd 作為註冊中心的案例也比較罕見。

當採用 zookeeper 作為 dubbo 註冊中心時,其註冊關係為樹形結構,詳細結構如下圖所示:

因為 zookeeper 是基於類似檔案系統的樹形結構來儲存資料,但 etcd 卻是採用鍵值對儲存,二者之間的差異會給註冊關係同步帶來較大困難。

此外,如果從 zookeeper 遷移到 etcd,則在整個遷移過程中:已有的線上服務不能受損,更不能停服;如果遷移失敗,還要能回退到到 zookeeper。

同城雙活與多活新架構

為了實現多活,我們通過跨資料中心的同步服務、服務依賴梳理與邊界劃分、可控變更等技術手段和運維理念,成功解決了以上挑戰,設計瞭如下一套新的架構來實現多活,如下圖所示:

圖二 鬥魚多活新架構

在新的架構下,可以按域名甚至是 URL 來細粒度的排程流量,RPC 層面也具備了自動就近呼叫的能力,其中註冊中心的區域性架構圖如下:

圖三 鬥魚註冊中心老架構

註冊中心多活方案選型與目標

在註冊中心多活改造過程中,我們面臨多個方案,如下表所示:



由於歷史原因,我們有 zookeeper(以下簡稱 zk)和 etcd 這 2 套註冊中心,加上我們有 Java、Go、C++、PHP 這 4 個技術棧,因此在註冊中心領域仍然一些不足,希望能統一到 etcd 來解決痛點問題,並達到以下目標:

降低維護成本:此前需要運維 zk+etcd 兩套註冊中心,更困難的是做多活解決方案時也需要適配 zk+etcd,這導致註冊中心多活研發成本翻倍。由於 etcd 是 k8s 的一部分,運維 etcd 又不可避免,這是選擇 etcd 的第 1 個原因。

擁抱更繁榮的生態:etcd 有云原生託管解決方案,有廠商通過 etcd 管理 10K node 級別的 k8s 叢集,etcd 還自帶 proxy、cache、mirror 等各種周邊工具,java 側 dubbo 也支援以 etcd 作為註冊中心,etcd 相對於 zk 來說發展前景更好,這是選擇 etcd 的第 2 個原因。

增強跨語言能力:etcd 可基於 http 或 grpc 協議通訊,並且支援長輪詢,具有較強的跨語言能力。而 zk 需要引入專用客戶端,除 java 客戶端之外,其它語言客戶端尚不成熟。而我們有 JAVA、Go、C++、PHP 等 4 種研發語言,這是選擇 etcd 的第 3 個原因。

基於以上原因,我們選擇了方案四,方案四大新架構如下圖所示:

圖四 鬥魚註冊中心新架構

註冊中心多活難點與挑戰

為了實現新註冊中心,達到我們期望的設計目標,註冊中心在改造過程中,面臨以下難點與挑戰:

如何解決 zk 的多資料中心同步問題?尤其是 zookeeper watch 機制是不可靠的,可能出現丟失 watch 事件的問題?(正確性)
如何解決 etcd 的多資料中心同步問題?從下面方案選型中,我們可以看到社群目前並無任何成熟、生產環境可用的解決方案。(正確性)
如何解決跨資料中心讀的效能問題?(效能)
如何解決跨資料中心的服務穩定性問題?網路鏈路上,比如內網專線若中斷了怎麼辦?同步服務設計上,是否會導致 etcd/zk 同步服務進入效能極慢的全同步邏輯,同步服務本身是否具備高可用等等?容災測試上,我們又該如何設計測試用例驗證?運維上,我們又該如何快速發現隱患、消除潛在的故障,建設視覺化、靈活的多活運維繫統?(穩定性、可運維性)

註冊中心多活難點分析

遷移過程中如何保證新舊服務互通?

開發 zk2etcd

我們很多 java 開發的業務使用 dubbo 框架做服務治理,註冊中心是 zookeeper,我們希望 java 和 go 開發的業務全部都統一使用 etcd 作為註冊中心,也為跨語言呼叫的可能性做好鋪墊。

由於業務眾多,改造和遷移的週期會很長,預計持續 1~2 年,在此過程中我們需要將 zookeeper 中的註冊資料同步到 etcd 中,實時同步,而且要保證資料一致性以及高可用,當前市面上沒有找到滿足我們需求的工具,於是我們和騰訊雲 TKE 團隊合作開發了一個 zk2etcd 來同步實現 zookeeper 資料到 etcd,並且已將其開源,整體方案落地篇我們將詳細介紹。

如何實現 etcd 異地容災?

通過 zk2etcd 同步服務,我們成功解決了 zookeeper 資料遷移問題,使得新老業務的註冊中心資料都使用 etcd 來儲存。

因此,etcd 的重要性不言而喻,它的可用性決定著我們的整體可用性,而鬥魚直播目前的部署架構又嚴重依賴某核心機房,一旦核心機房出現故障,將導致整體不可用。因此鬥魚直播下一個痛點就是提升 etcd 的可用性,期望實現 etcd 跨城容災、異地容災能力。

鬥魚直播理想中的 etcd 跨城同步服務應該具備如下特性:

etcd 跨城容災部署後,讀寫效能不顯著下降,能滿足業務場景基本訴求。
同步元件達到生產環境可用級別,具備完備的一致性檢測、日誌、metrics 監控等。
對資料一致性要求不強的業務可就近訪問同地區的 etcd 叢集服務、強一致訴求業務可訪問主 etcd 叢集。
主叢集故障後,業務運維能根據一致性監控等,快速將備叢集提升為主叢集。
那麼有哪些方案呢?各個方案又有哪些優缺點呢?最終評估瞭如下幾種方案:

單叢集多地部署方案

etcd 社群 make-mirror 方案
etcd 社群 learner 方案
騰訊雲 etcd-syncer 方案
單叢集多地部署方案
單叢集多地部署方案圖如下:

在此方案中,etcd Leader 節點通過 Raft 協議將資料複製到各個地域的 Follower 節點。

此方案它的優點如下:

各地域網路互通後,部署簡單,無需運維額外元件

資料跨城強一致同步,3 節點部署場景中,可容忍任一城市故障,並且不丟失任何資料

介紹完它的優點後,我們再看看它的缺點,如下所示:

在 3 節點部署的場景下,任意寫請求至少需要兩個節點應答確認,而不同節點部署在各地,ping 延時會從幾毫秒上升到 30ms 左右(深圳 - 上海),因此會導致寫效能急劇下降。

etcd 預設的讀請求是線性讀,當 Follower 節點收到 Client 發起的讀請求後,它也需要向 Leader 節點獲取相關資訊,確認本地資料追趕上 Leader 後才能返回資料給 client,避免讀取到舊資料等,在這過程中也會導致 etcd 讀延時上升、吞吐量下降。

跨城部署網路之間質量也較容易波動,導致服務質量抖動等。

client 訪問 etcd 叢集的配置,為了防止單點故障,必須配置多個 etcd 節點,而這又可能導致 client 訪問到異地的 etcd 節點,導致服務請求延時增大等。

etcd 社群 make-mirror 方案

介紹完單叢集多地部署方案後,我們再看看 etcd 社群提供的 make-mirror 方案,它的原理圖如下:

在此方案中,我們分別在不同城市部署了一套獨立的 etcd 叢集,通過 etcd 社群提供的 make-mirror 工具實現跨城資料複製。

make-mirror 工具原理如下:

指定資料同步的字首後,通過 etcd Range 讀介面從主叢集遍歷此字首下的所有資料,寫入到目的 etcd。(全量同步)
隨後通過 etcd Watch 介面指定讀請求返回的“版本號”,監聽從此版本號後的所有變更事件。
make-mirror 收到主 etcd 叢集推送的 key-value 變化事件後,通過 txn 事務介面將資料寫入到熱備叢集。(增量同步)
此方案它的優點如下:

主 etcd 叢集讀寫效能高,整體上不受跨地域網路延時、網路質量波動影響
若業務可容忍短暫不一致,可就近訪問距離最近的 etcd 叢集
若業務要求強一致,可通過內網專線訪問主 etcd 叢集
不依賴高版本 etcd
介紹完它的優點後,我們再看看它的缺點,如下所示:

當寫請求較大的時候,備叢集可能存在一定的資料落後,可能讀到髒資料。
社群自帶的 make-mirror 同步鏈路中斷後,退出重啟會再次進入全量同步模式,效能較差,無法滿足生產環境訴求。
社群自帶的 make-mirror 工具缺少 leader 選舉、資料一致性檢測、日誌、metrics 等一系列特性,不具備生產環境可用性。
不支援同步非 key-value 資料,如 auth 鑑權相關資料、lease 資料等。

#### etcd 社群 learner 方案
介紹完 etcd 社群的 make-mirror 方案後,我們再看看 etcd 社群提供的 learner 方案,它的原理圖如下:

它的核心原理如下:

etcd raft 演算法庫在 2017 年的時候就已經支援了 learner 節點,詳情可參考 pr 8751。
etcd 社群在 2019.8 月推出的 3.4 版本中,正式支援 Learner 節點,它作為非投票 (Non-Voting) 的成員節點加入叢集,不參與叢集選舉等投票,只進行資料複製。
Leader 收到寫請求後,將日誌同步給 Follower 和 Learner 節點,並在記憶體中使用一個名為 Progress 的資料結構,維護 Follower 和 Learner 節點的日誌同步進展資訊。
當 Learner 節點的資料與 Leader 資料差距較小的時候,它就可以被提升為可投票的成員節點加入叢集。
此方案它的優點如下:

各地域網路互通後,部署簡單,只需往 etcd 叢集中新增一個 Learner 節點,無需運維額外元件
Learner 節點可同步任意型別資料,如 key-value、auth 鑑權資料、lease 資料
介紹完它的優點後,我們再看看它的缺點,如下所示:

Learner 節點只允許序列讀,也就是業務如果就近讀,會讀到舊資料。
依賴高版本 etcd,etcd 3.4 及以上版本才支援 Learner 特性,並且只允許一個 Learner 節點 .
主叢集全面故障後,無法快速將 Learner 節點提升為可寫的獨立 etcd 叢集。
介紹完已有的幾種方案後,我們發現它們都無法滿足業務生產環境訴求,於是我們自研完成了生產環境可用的 etcd 同步服務落地,在整體方案落地章節將詳細介紹。

如何確保 etcd 和 zk 同步服務的穩定性、可運維性?

為了確保 etcd、zk 同步服務的穩定性,模擬 5 類常見的故障,檢驗服務在這些典型故障場景下的自愈能力,詳細測試方案如下。

#### 故障場景
redis 閃斷(zk2etcd 服務依賴),例如:redis 版本升級、非平滑擴容。

zk2etcd 離線,例如:OOM、容器驅逐、宿主機故障。

etcd2etcd 離線 ,例如:OOM、容器驅逐、宿主機故障

網路閃斷,例如:OOM、容器驅逐、宿主機故障。

弱網環境,例如:專線斷掉後臨時用公網頂替。

上述 5 種場景的實際觸發原因有多種多樣,只需要模擬出一種情況。

演練方案

redis 閃斷:通過改 host 模擬 redis 不可達,此時自動訂正停止;模擬 redis 恢復後,自動訂正亦自動恢復。

zk2etcd 離線:通過殺容器節點模擬 zk2etcd 掛掉,15 秒內 k8s 自動拉起,拉起完成後同步正常、資料一致。

etcd2etcd 離線 :通過殺容器節點模擬 zk2etcd 掛掉,15 秒內 k8s 自動拉起,拉起完成後同步正常、資料一致。

網路閃斷: 通過改 host 模擬 zk、etcd 不可達,此時同步中斷,後去掉 host 模擬網路恢復,恢復後同步正常、資料一致。

弱網環境: 通過切公網模擬弱網環境,切公網後同步效率降低在 4 倍以內,1 次全量同步仍然可在 1 分鐘內完成。

另外針對可運維性問題,無論是 etcd 還是 zk 同步服務,都提供了詳細的 metrics、日誌,我們針對各個核心場景、異常場景都配置了視覺化的觀測檢視,並配置了告警策略。

整體方案落地

整體架構

etcd 叢集多活架構圖如下所示:

說明

黑實線:正常情況下的專線訪問

黑虛線:切公網方式訪問

紅實線:etcd 叢集發生主備切換後的專線訪問

紅虛線:etcd 叢集發生主備切換後的公網訪問

etcd2etcd/zk2etcd 資料同步服務圖如下所示:


zk同步服務工程化實踐

zookeeper 與 etcd 儲存結構不一致,加大了同步的實現難度。zookeeper 儲存是樹狀結構,而 etcd v3 是扁平結構。zookeeper 無法像 etcd 一樣按照 prefix 來 list 所有 key;etcd 無法像 zookeeper 一樣通過 list chilren 來查詢某個目錄下的子節點,也加大了實現同步的難度。

如何感知 zookeeper 中的資料變化?zookeeper 的 watch 不像 etcd 一樣可以簡單的感知到任意 key 的新增,需要遞迴的 watch 所有的節點,收到 ChildrenChanged 事件後拿到該事件對應節點下的所有子節點,再與 etcd 中的資料進行比對,就可以得到新增的資料,並將其同步 put 到 etcd 中。類似的,可以用遞迴的方法 watch 所有節點的刪除事件,並同步刪除 etcd 中的資料。

另外 zookeeper 的 watch 有著先天性的缺陷,watch 是一次性的,所以每次收到事件後又必須重新 watch,兩次 watch 之間理論上是可能丟事件的,主要是在同一個 key 連續多次變更的時候可能會發生。如果丟事件發生就會破壞了資料一致性,我們引入了自動 diff 和訂正的能力,即計算 zookeeper 和 etcd 中資料存在的差異,每次都會經過兩輪 diff 計算,因為在頻繁變更資料的情況下,一輪 diff 計算往往存在一些因不是強一致性同步導致的"偽差異",當 diff 計算出了結果就會自動 fix 掉這些差異。

如何解決與 etcd2etcd 共存?當同一個路徑下,即有 etcd2etcd 同步寫入的資料,又有 zk2etcd 寫入的資料,在 zk2etcd 的自動訂正邏輯裡面,會計算出差異並訂正差異,但我們不希望因此而誤刪 etcd2etcd 寫入的資料。我們通過為 zk2etcd 引入了 redis 來儲存狀態解決了這個問題,在 zk2etcd 往 etcd 中同步寫入或刪除資料時,也同步在 redis 中記錄和刪除:

然後 zk2etcd 在自動訂正計算差異的時候,只考慮本工具寫入過的資料,避免誤刪其它同步工具寫入的資料。

etcd2etcd 工程化實踐

為了解決 etcd 同步難題,我們調研瞭如下兩種方案,接下來我們就詳細介紹下它的原理:

etcd-syncer 之 mirror-plus 版

首先我們介紹下 etcd-syncer 的 mirror-plus 方案,顧名思義,它是 etcd 社群 make-mirror 的加強版。為了解決 make-mirror 的各種缺陷,它實現了以下特性、優點:

支援多種同步模式,全量同步、斷點續傳,不再擔憂專線、公網網路質量抖動
高可用,負責同一資料路徑複製的例項支援多副本部署, 一副本故障後,其他副本將在 5 秒後獲得鎖,在之前例項同步的進度基礎上,進行快速恢復
支援一致性檢查(全量資料檢查、快照檢查)
支援多例項併發複製提升效能(不同例項負責不同的路徑),建議生產環境配置多例項,每個例項負責不同路徑
良好的運維能力,基於 k8s deployment 一鍵部署,豐富的 metrics、日誌,完備的 e2e 測試用例覆蓋核心場景(http/https 場景,服務異常中斷、網路異常等 )
那麼它的缺點是什麼呢?因為它核心原理依然是依賴 etcd 的 mvcc+watch 特性,因此資料無法保證強一致性和只同步 key-value 資料。

斷點續傳依賴 mvcc 歷史版本保留時間,最好業務能儲存至少 1 個小時的歷史資料。
當寫請求較大的時候,備叢集可能存在一定的資料落後,可能讀到髒資料。
不支援同步非 key-value 資料,如 auth 鑑權相關資料、lease 資料等。

etcd-syncer 之 Raft 版

為了解決所有型別的資料同步問題以及消除對 etcd mvcc 歷史資料的依賴,騰訊雲還可提供基於 Raft 日誌的同步方案 etcd-syncer 之 raft 版本。

它的部署圖如下所示,etcd-syncer 同步服務作為一個類似 learner 節點的身份,加入主 etcd 叢集。

主 etcd 叢集 Leader 將 Raft 日誌資料通過 MsgApp/Snapshot 等訊息同步給 etcd-syncer, etcd-syncer 解析 Raft 日誌,將 Raft 日誌條目對應的 Txn/Delete/Auth 等請求應用到目的 etcd 叢集。

它具備如下優點:

具備 etcd-syncer 之 mirror-plus 版本的所有特性和優點,同時不依賴 etcd mvcc 歷史資料。

基於 etcd 底層的 Raft 日誌同步資料,可以同步 key-value、auth、lease 等各種型別的資料。

不依賴高版本的 etcd。

完備的容災測試

#### grpc-proxy
此方案引入了 grpc-proxy 代理服務,也是頭一次使用。為了瞭解此代理服務的效能情況,我們使用 etcd 自帶的 benchmark 進行了讀和寫的測試,另外手寫了一個小工具做了一下 watch 測試。以下為部分測試內容。

寫入測試

直接訪問 etcd 服務的負載均衡入口

走 grpc-proxy 代理訪問 etcd 服務的情況

grpc-proxy 代理在 endpoints 配置走專線或公網情況下,都能正常寫入
寫入 key 總數一定的情況下,連線數和客戶端數越大,總耗時越低
寫入 key 總數越大,單次寫入的平均耗時(Average)會有所增加,但仍為毫秒級
當一次寫入 key 總數為 10 萬時,直連 etcdserver 會出現 too many requests 的報錯,但 grpc-proxy 沒有
公網情況比專線效能有所下降
走 grpc-proxy 代理的平均耗時相比直連有所增加,但滿足需求
讀取測試

直接訪問 etcd 服務的負載均衡入口

走 grpc-proxy 代理訪問 etcd 服務的情況

grpc-proxy 代理在 endpoints 配置走專線或公網情況下,都能正常讀取

走 grpc-proxy 代理的平均耗時相比直連有所增加,但在可接受範圍

watch 測試

根據我們自己寫的一個 etcdwatcher 服務對 grpc-proxy 進行 watch 測試:可以設定總 watcher 數量,更新頻率,以及測試時間,結束時列印出簡報

./etcdwatch -num=100 -span=500 -duration=10 -endpoint=http://grpc-proxy-addr:23791
test done
total 100 task
0 task failed
current revision is 631490
least revision is 631490
0 task is not synced

引數說明:

num 任務數量

span 更新間隔,單位毫秒

duration 總測試時間,單位秒

current revision:代表寫入的 revision

least revision:表示 num 個任務中同步最慢的 revision

failed 為 0 說明正常;如果過出現 task not sync 說明 watch 和 put 不同步

以上測試結果來看:failed 數為 0,watch 測試正常

zk2etcd

我們使用的是 1.2.5 版本,通過 k8s 的 deployment 方式部署

模擬 zk server 失聯

場景
通過將 hosts 中注入錯誤解析地址

現象
期間沒有發現 zk 失聯的報錯日誌
監控指標沒有發現異常
此後執行重啟,fixed 運算元沒有出現凸增情況(在 1.2.4 版本中,存在 full sync 雖然在定時執行,但是並沒有感知到需要 fix 的 key 的 bug。導致重啟 zk2etcd 服務例項後,可能觀察到 fixed 操作凸增的現象)

模擬 redis 失聯

模擬操作
09:56:49 將 hosts 中注入 redis 錯誤解析地址
10:07:34 恢復 redis
10:16:00 重啟同步服務 pod(操作重啟是為了觀察 full sync 是否正常)

現象
期間 fixed operation 數量沒有增長,其他監控指標未發現明顯異常
例項重啟後沒有出現 fixed 數凸增的情況

模擬etcd失聯

模擬操作
16:15:10 etcd server 失聯

16:30 恢復

16:45 重啟 pod

現象
期間 fixed operation 數量沒有增長,其他監控指標未發現明顯異常

此後重啟,fixed operation 數量有所增漲(不能確定是 full sync 未生效,還是重啟後剛好有更新修復導致)

總結

只要 full sync 機制工作正常,各異常場景發生後,都能在下一個 full sync 觸發後被恢復

恢復的最小時間間隔取決於設定的 full sync 定時執行間隔時間(預設為 5m),業務對此間隔時間容忍情況自行調整引數

此外,為了避免異常發生後,full sync 機制定時執行但也沒能感知到情況發生,保險起見事後可以第一時間重啟一下 zk2etcd 服務

對於追加的 etcd 公網測試,full sync completed 和 zk、etcd 操作耗時,相比內網情況有一定(秒級)增長

etcd2etcd

etcd2etcd 的同步服務,我採用 deployment 雙副本部署

多副本 backup 能力

期望
⼯作節點故障後備⽤節點會在 5s 後接管同步任務

測試方案
etcd syncer 雙例項部署

殺掉正在執行的工作節點進行觀察

結論
不論是增量同步還是全量同步過程中,主備切換都能正常工作(需要注意的是,當全量同步中發生主備切換後會變為增量同步,從而可能導致比對較慢)

斷點續傳能力

期望
故障恢復後能從斷點繼續開始同步

其實在第 1 部分,備節點切換為主後接管同步工作,fast_path 變為 1 也證明了斷點續傳能力,我們還額外補充幾個驗證場景:

(a) 短時間故障

故障場景

中心 etcd 叢集到熱備叢集的同步過程中,因作為源的中心 etcd 叢集中也存在 -etcd-syncer-meta- 的 key,觸發了同步服務報錯(同 txn 中不能包含相同的 key),出現了資料差異

現象

將同步服務執行引數新增對 -etcd-syncer-meta- 的過濾,然後觀察進過一段時間追趕資料後,最終 miss 數降去達到一致

(b) 長時間故障

故障場景

停止同步服務的部署 deployment

等待兩邊 etcd 叢集產生資料差異,併發生一次 compact 後再啟動同步服務

現象

等產生資料差異,併發生 compact 後,重新啟動同步服務,其日誌如下:因 compacted 發生,觸發全量同步

同步服務監控指標:(a) dst miss key 很快降下去;(b) src miss key 有所增加,並持續不降

分析

同步服務停止以後,源 etcd 的 key 數量發生不少變化,監控圖看出期間有下降,說明發生過 key 的刪除

這裡也暴露出一個小問題,當出現 src miss key 的時候,目前不能自動修復,需要人工接入清理多餘的 key

  1. reset 觸發全量同步

當同步發生重大差異(如,發生 dst miss)進行緊急修復的時候,通過配置 --reset-last-synced-rev 引數刪除斷點續傳資訊,來觸發全量同步修復差異

現象
因某種異常,同步出現 dst miss(圖中黃線例項)的情況。為了進行修復,新例項新增 --reset-last-synced-rev 引數後執行

分析

slow_path 為 1,說明觸發全量同步(圖中綠線例項)

綠線例項的 dst miss 值沒有增長起來,說明已經達到一致

  1. 網路故障
    兩 etcd 叢集之間專線中斷

增量同步中

全量同步中

測試方案

當專線中斷切換公網時,需要修改執行引數中的 etcd 叢集訪問地址,即:必會發生重啟(重啟場景測試前面已經涵蓋,這裡不再重複)

總結

etcd-syncer 同步服務有較好的主備機制,能夠及時有效的進行切換

短時間故障後的斷點續傳表現符合預期;對於長時間故障,同時發生 compact 的複雜情況時,恢復同步後出現 src miss 的情況,可能需要人工接入

通過配置 --reset-last-synced-rev 引數對 src miss 的異常修復有較好的效果

關於我們

更多關於雲原生的案例和知識,可關注同名【騰訊雲原生】公眾號~

福利:公眾號後臺回覆【手冊】,可獲得《騰訊雲原生路線圖手冊》&《騰訊雲原生最佳實踐》~

相關文章