開發

棒球比分直播雪缘园:萬億級消息背后:小米消息隊列的實踐

前文《消息隊列價值思考》講述了消息中間件在企業 IT 架構中的重要價值,本文將呈現這些價值在落地小米業務過程中的遇到的問題和實踐經驗;其主要內容是流式平臺團隊在 SACC 2019 (sacc.it168.com)大會上分享的主題,這里簡單整理成文,供大家參考,其中一些重要問題的細節會在后續文章陸續展開;
今天的主題主要包括以下幾個方面的內容:

  • 業務背景:消息隊列在小米落地的業務背景
  • 架構與關鍵問題:小米自研分布式消息隊列 Talos 的架構和關鍵問題
  • 性能與資源優化:業務爆發式增長,Talos 在性能和資源方面的挑戰與實踐經驗
  • 平臺化效率:舉例 Talos 在平臺化過程中提升效率的一些實踐
  • 未來規劃:小米消息中間件的規劃和愿景

業務背景小米內部在 2015 年之前使用的是 Kafka 0.8 版本,當時的痛點比較多,由于 Kafka 本身是存儲計算耦合的架構,使得數據不均衡的問題經常凸顯,集群擴容、故障恢復也變得異常麻煩,給運維工作帶來不少痛苦;同時,由于 Consumer 的 Rebalance 算法每次都是全部重新計算,使得業務的消費體驗也不是很好; 
作者批注:存儲計算耦合的架構在擴容和故障轉移時都需要進行數據搬遷;故障恢復時一般要經歷復雜的算法先選舉 Leader,且提供服務前要先保證各副本數據是一致的

我們期望能有一個快速擴容、無狀態無感知的消息隊列,同時具有很好的容錯機制,故障時可以快速恢復,減少運維的復雜度;消費端希望發生變化時能有一個最小損失的算法,讓消費盡量平滑;同時這個系統需要高度定制化,以滿足小米內部業務和生態鏈公司的需求,比如多租戶相關的特性,跨機房的 Replication 機制等; 
作者批注:當時開源的消息隊列在多租戶方面都不是很完備,更多傾向在數據管道或解耦RPC調用的特性上在這樣的背景下,有了小米自研的分布式消息隊列:Talos,它立項的目標是對內滿足小米各部門的業務需求,對外為生態鏈公司輸出中間件能力,系統本身對標 AWS Kinesis 與 Apache Kafka。

我們來看一下 Talos 目前在小米系統架構中的角色,主要有兩種:在線的消息隊列與數據集成平臺的總線;

在線消息隊列主要是直接使用 Talos 的 SDK — Producer 和 Consumer 來生產、消費消息;數據集成平臺總線如下圖,左側是各種數據源,Talos 平臺為用戶提供了連接各種數據源的 Source Connector,比如 Web Source、Agent Source、BinLog Source 等,這些組件可以幫助業務將埋點數據、日志文件、BinLog日志等導入到 Talos;平臺會根據用戶在產品界面配置的 Sink 需求自動將數據 transfer 到下游的各種存儲/檢索系統中,比如 HDFS、Kudu、ElasticSearch 等,然后用戶可以使用各種計算引擎訪問/查詢這些數據,輔助 BI 決策; 架構與關鍵問題Talos 是一個存儲計算分離的架構,底層基于 HDFS 來存儲實際的 Message,使用 HDFS 也是得益于小米在存儲方面多年的深耕和積累;上層 Talos Server 是無狀態無中心的計算節點,使用一致性哈希作為 Partition 調度和負載均衡的策略;

當 Producer/Consumer 讀寫時,Talos Server 收到請求后首先會根據一致性哈希計算所請求的 Topic-Partition 應該由哪一臺機器 Serve,如果是由自己 Serve,則直接向 HDFS 發起請求;如果是由其他機器 Serve,則會先做一次轉發。Talos 系統的一些 Meta 信息存儲在 ZooKeeper 中,除此之外,一些控制流信息也是通過 ZK 來完成,比如 Talos Server 的上下線,Topic DDL 相關的操作廣播等。

作為存儲計算分離的架構,計算層 TalosServer 負責 Topic 的邏輯分區 Partition 的調度和管理,存儲層 HDFS 負責具體物理分片的存儲和高可用,這樣的分層是有不少優點的: 
1)計算層由于無狀態,管理調度都非常簡單,天然支持水平擴展,擴容迅速;故障轉移也更加快速簡單,不需要關心數據的同步和一致性,專注于計算邏輯; 
2)存儲層專注數據管理的高可靠和高可用,使用現有比較成熟的存儲系統,可以間接降低系統復雜度;作者批注:相比計算框架的快速更新換代,存儲系統這些年相對比較成熟,迭代一般是性能方面的提升;依賴 HDFS,可以讓 Talos 在數據存儲方面走“捷徑”在這樣的架構設計下,實現 Talos 系統有幾個問題是比較關鍵的,這里列舉三個說明;

首先是 DFS Client 的 Tailing Read,我們知道 HDFS 正在寫入的 Block 數據對用戶是不可見的,但是消息隊列的使用場景大部分都是邊寫邊讀的,為了能夠支撐 Talos 的場景,小米內部對 HDFS Client 做了改造,使其支持最后一個 Block 的 Tailing Read;其次是 Talos 的一致性模型,即必須保障對于某個 Partition,同一時刻只有一個 TalosServer 寫入,否則就會出現腦裂;Talos 規避腦裂的機制主要包括兩方面:1)利用 HDFS RecoverLease 保證 Partition 發生遷移時最后一個文件不會再被寫入;2)設計特定的 Fencing 機制來保證 Partition 對應的文件目錄的操作原子性;通過這兩方面來保證 Talos 寫操作的一致性,詳細細節可以關注后續文章《Talos一致性模型》。 
作者批注:這里的 Partition 在物理上實際對應的是 HDFS 的一個目錄第三個問題是分區延遲分配,由于 Talos 采用一致性哈希進行 Partition 調度,當集群滾動升級或某個節點重啟時,就會帶來 Partition 的遷出以及重新遷入,這種開銷是完全可以避免的,尤其當集群比較大時,這種頻繁的遷移會導致很差的消費體驗;Talos 使用一種 Partition 延遲分配的策略來規避這個問題,減少因為頻繁遷移帶來的通信開銷和網絡開銷,保證消費的平滑。 性能與資源優化

隨著業務規模的爆發式增長,Talos 在性能和資源方面也遇到一些瓶頸與挑戰,目前 Talos 的規模大致如上:

  • 日處理消息數超過 2萬億條,日消息峰值 4千萬條/秒,日處理數據量 1.3PB
  • Topic 總數 13000+,下游的作業數 15000+,接入業務數量 350+ 

面對這樣規模的背景下,Talos 在性能和資源方面的優化主要包括以上幾個方面,接下來我們針對各方面一一展開。首先是線程模型的改造。Talos 開始使用的讀寫線程模型就是一個簡單的線程池,當一個請求到來時哈希到不同的線程上處理,這樣做的問題是,當有一個 Topic 的請求卡主或變慢時,會影響在這個線程上排隊的其他 Topic 的請求;我們希望既能盡量避免不同 Topic 請求間的相互影響,又能充分利用空閑的線程,于是做了一個“具有記憶功能的最小堆”線程池,如下圖右邊所示

這個線程池包含兩部分,一部分是記錄當前正在線程上排隊的請求個數的線程最小堆,一部分是記錄當前正在 runtime 的 Topic 請求對應的處理線程;假設 T1_P1 表示 Topic1-Partition1 的請求,當有新的 T1_P1 請求到來時,首先看記錄表中是否有線程正在處理 T1_P1 的請求,如果有則使用相同的線程,如果沒有則從最小堆中取一個最空閑的線程來處理;這樣既能保證當有請求變慢或卡住時,盡量不會影響其他的請求,也能最大化利用空閑的線程。 

由于 Talos 存在轉發的情況,轉發線程也存在互相干擾的問題,例如同一個節點轉發到其他不同節點間可能互相影響,轉發讀請求和寫請求之間也會互相影響,這一部分我們也做了改造;最后我們總結了線程模型改造的經驗:核心原則是避免競爭,具體展開可以分為三個方面:1)不同處理對象之間,例如不同的 Topic-Partition 請求;2)不同的操作之間,例如讀與寫;3)一個流程有多個步驟,將耗時步驟分解出來使用單獨的線程處理;

第二部分是寫優化,簡單總結就是將多次小 I/O 合并成大 I/O,提升系統響應和吞吐。Talos 為了實現數據不丟的語義,對于客戶端的每一次寫請求,服務端都會執行一次 HDFS flush,如上圖,對于 Partition1 的 3 次請求,會調用 3 次 flush;這種情況在流量突增或高 QPS 場景下會比較吃力;

傳統的生產者消費者模型每次都是從隊列中取出一個 Task 消費,我們在現有 Task 的基礎上抽象出一個虛擬的 Task,當某個 Partition 的請求被處理時,它會拿到當前這個時刻到達 Server 端該 Partition 所有的請求,并將其合并成一個大的 I/O,進行一次整體 flush,如果成功則拆開多次返回給客戶端成功,如果失敗則拆開多次分別返回給客戶端異常信息;這樣的優化后單機 QPS 從 1K 提升到 1W+,在同樣 QPS 的壓力下,延遲也有很大提升,例如在單機 5000 QPS 的情況下,P99 延遲從 70ms 降低到 5ms

一般來講,絕大部分系統應該不會遇到上下文切換帶來的煩惱,但是在高并發場景下,線程數設置的過多會大大降低系統性能;除了設置過多的線程,競爭鎖也會帶來上下文切換,持鎖時間、持鎖粒度,wait-notify 等使用不合理都會帶來上下文切換的負擔;此外 GC 也是帶來上下文切換的重要因素;為了避免上下文切換影響系統性能,可以將這個指標放在服務性能監控的展板中,隨時觀測防患于未然;Talos 在 GC 問題上經歷了三個階段,最早是頻繁 CMS 帶來的延遲影響,對內存參數調優后解決這個問題,但是每過一段時間,大概 20-30 天的周期,就會進行一次 Full GC,對延遲敏感的線上業務就會受到影響;Talos 在將 GC 算法改為 G1 時進行了適當的調優,調優使用的工具是 HotSpot 開發的 gc 日志工具,這其中最重要的是要確定服務的常駐內存,依此設置好 IHOP,然后調整 Young GC 的耗時以及觸發 Mixed GC 的時間間隔等; 

如上圖是調優前后的 GC 耗時對比,經過針對性調優,GC 耗時由之前的大部分高于 100ms 變為 70ms 以內; 

對于高吞吐型的服務,帶寬資源往往會成為瓶頸,針對帶寬 Talos 主要做了兩方面工作:客戶端尋址與基于流量的個性化一致性哈希;通過計算我們發現基于轉發模型的 Talos,有 95% 以上的請求都需要被轉發,這會帶來很大的帶寬消耗,客戶端尋址讓帶寬資源節省了 40%,同時由于省略了轉發,P95的延遲也優化了 50%。

通過一致性哈希來負載均衡,Talos 每個節點 Serve 的 Partition 個數基本上是均勻的,但由于業務數據的多樣性,Partition 之間的流量差別是很大的,這就會帶來 I/O 的不均衡,從而影響系統性能;如上圖,左側 3 個節點都有 5 個 Partition,但是節點 2 與 節點 3 之間的流量差值卻有一倍多,我們希望通過一些策略,可以達到右側的效果,讓節點間的流量趨于均衡;Talos 對一致性哈希做出了改造,通過引入流量因子,對一致性哈希中每個物理節點智能調整其虛擬節點的個數,從而影響物理節點 Serve 的 Partition 個數,來達到流量的均衡;具體來講: 
1)Talos 會獲取每個物理節點歷史的日均流量,根據集群節點個數,計算出每個節點平均的日均流量期望值 
2)以期望值為標準,大于期望值的節點會被減少虛擬節點數量,反之會被增加虛擬節點 
3)虛擬節點變化后會重新計算 Partition 的分布,然后根據 Partition 流量算出各個節點新的流量分布 
4)重復多輪調整直到流量分布達到預期閾值 

如上是 Talos 一個集群負載均衡優化前后的對比圖,橫坐標是節點機器 ID,縱坐標是節點的日均流量,優化后機器間日均流量的差值縮小了 50%+,具體細節可以關注后續文章《Talos負載均衡實踐》;作者批注:一致性哈希的個性化改造可以廣泛應用到各種指標,比如流量、QPS等;相關的專利正在申請中平臺化效率Talos 在平臺化的演進中,監控和計量是不可忽視的一部分,為了能滿足高效、高吞吐、統一的監控與計量需求,我們抽象出一套通用的框架服務于各???,主要包含三部分:指標收集、指標整理以及指標展示; 

各??榧?Talos 服務本身的進程會將需要的指標打到本機部署的 Agent,Agent 會將指標轉到 Talos 特定的 Topic 中,后端會有高可用的流式作業將數據實時導入 Druid,必要時做一些指標整理,然后基于 Druid 將重要的指標展示到 Dashboard 與 Falcon 中,供監控和報警;其中一些機器級別等不需要聚合的指標也會直接推送到 Falcon 用于報警使用;基于以上的流程,Talos 提供了一套多維度(服務維度/集群維度/機器維度)、多視角(用戶視角/開發視角/運維視角)的指標監控與運營平臺;同時 Talos 服務的計量計費也是基于這套框架來對各部門業務的數據進行實時計量與計費; 

作為平臺,不可避免的問題是資源管理,對于 Talos 來說,就是 Partition 資源配額的申請與審批;之前是人工管理,耗費了大量的精力和時間,我們對業務的真實流量和 QPS 做了統計,模擬出真實增長需求的閾值,然后對比資源配額的申請發現,有 70% 的需求都是在這個閾值以下,可以直接審批通過的;有 28% 的單子是用戶夸大了需求,會造成資源浪費;超過閾值且真實的需求很少,只有這部分才需要人為干預,去評估業務這種突然很大配額需求;我們把夸大需求的各種 Case 抽象成異常,讓平臺自動拒絕申請并提示拒絕原因和存在的問題;對于真實需求的情況自動審批,實現資源管理的自動化和申請自助化,節省了絕大部分的人工支持工作; 作者批注:業務再也不用擔心/催促資源申請無人審批的問題了小米消息中間件的規劃與愿景  

最后談一下小米中間件的規劃與愿景,大致分為兩個部分:

  1. 持續貼緊業務,價值輸出
    • 首先,我們需要做好重要特性賦能關鍵業務。例如 Transaction 落地電商金融等場景,Replication 落地云服務等場景。
    • 其次,小米在電商、金融的發展越來越迅速,作為企業級消息系統,需要為此做好準備。我們希望未來能夠打造金融級的分布式消息系統,為電商金融等場景提供靠譜的中間件能力;為此,業務對系統的高可靠、一致性、高可用、性能等方面都會提出更高的要求和挑戰,比如高可用會需要真正的同城多活、異地多活等能力;
  2. 持續學習業界,建設小米中間件技術能力
  3. 消息中間件近年的發展開始慢慢引入算力,通過輕量化計算,使得消息系統從傳輸數據向理解數據發展,我們希望借此將小米的消息中間件打造成智能傳輸+計算的服務平臺,為業務提供更好的平臺化服務;
  4. 作為云原生時代架構的重要組成部分,消息中間件也需要持續跟進業界,進行 ServiceMesh 與 Serverless 架構的探索和升級;實際運維過程中,我們發現傳統富客戶端確實會帶來各種各樣的耦合問題,我們希望探索 Message Mesh 這種下一代消息傳輸架構,提升業務效率。

小米云平臺部,主要分享云存儲、云計算、系統、網絡、運維、私有云、安全、數據庫、內核等內容,歡迎感興趣的朋友們關注!

Transformer 在美團搜索排序中的實踐

上一篇

360收購億方云,曲線進軍云計算細分市場

下一篇

你也可能喜歡

萬億級消息背后:小米消息隊列的實踐

長按儲存圖像,分享給朋友

ITPUB 每周精要將以郵件的形式發放至您的郵箱


微信掃一掃

微信掃一掃
{ganrao} 美人捕鱼游戏下载 福彩6十1牛材网 天津麻将下载官网 体彩幸运赛车开奖直播 意甲西甲 黄金棋牌游戏? 美林配资 浙江6 1体彩开奖结果 南昌期货配资 平特肖的概率有多少 江西十一选五历史开奖记录 手机捕鱼有哪些技巧 神来棋牌怎么坑人的 海南飞鱼彩票开奖结果 安徽11选5基本走势图 做什么网站最赚钱