計算與儲存分離實踐—swift訊息系統
1. 相關背景
搜尋事業部與計算平臺事業部目前使用訊息佇列主要有以下三種場景:
1. 每天有上萬張表需要通過Build Service來構建索引。這些表主要來自主搜尋,IGRAPH,Rank Service等業務,且每個表包含的文件數差別很大。總資料量為PB級別,總文件數達萬億級。文件的大小不一,小到幾十Byte大到幾百KB。在Build Service內部,文件處理與索引構建需要一個訊息佇列來傳送訊息。因此在build時,容易產生突發大流量(幾百G/秒,幾千萬條/秒)持續訊息寫入與讀取。
2. 搜尋的線上服務如主搜尋查詢服務,RankService打分服務或IGRAPH服務需要毫秒級的實時文件更新。這些服務引擎基本上是多行多列結構,即每一行是一個完整的服務單元,由多臺機器組成,多行提升服務的總能力。大的服務通常包含數百行,所以一條實時訊息通常會被消費數百次,線上同時實時消費的機器規模也達上萬臺。
3. 線上的實時訊息主要來自離線實時模型訓練,使用者的實時瀏覽、點選、加購行為或者商家的增刪改寶貝等。離線訓練任務會同時啟動幾十萬個worker對上千張表產生實時訊息,寫請求每秒達千萬次。
對於這幾種場景,傳統的訊息佇列(如Kafka等)要同時滿足,至少需要成百上千臺物理機,且系統還需要做改造來適用於每天上萬個topic的增減和幾十萬的生產者與消費者同時讀寫訊息。另外這些機器的failover管理也是個大問題。現實中,搜尋團隊所有的機器都是由排程系統統一管理和複用,沒有專門的物理機可給訊息系統獨佔使用。
本文將介紹搜尋事業部目前使用訊息系統swift。主要介紹系統結構和訊息可靠傳遞機制這兩方面。最後介紹下swift系統在今年雙十一期間的表現。
2. Swift介紹
傳統的訊息佇列通常為訊息的安全性,一般先要求訊息落盤到本機後才返回成功。這限制的機器的遷移,擴充套件和複用。因為訊息資料只存一兩臺機器,機器遷移必然導致資料的遷移。傳統訊息佇列要有較高的效能,通常先要解寫磁碟的毛刺等io問題。特別是機器與其它應用複用時IO問題並不好解決。所以傳統的訊息佇列一般要求機器獨佔使用。
計算與儲存分離一直是最近年來研究與應用的熱點。計算與儲存分離帶來最大的好處是機器的遷移與排程不再受到資料儲存大小與位置的限制。計算資源在排程系統的管理下可以近無限的擴充套件。儲存系統如HDFS,PANGU能提供的PB級的儲存空間以及百萬級的檔案讀寫。
計算與儲存的分離在訊息中介軟體系統中的應用還比較少,主要的問題是傳統的分散式檔案系統的讀寫響應latency遠大於本機的磁碟。如果要保證訊息先落盤,導致整個請求的latency就會飆升,影響整個訊息系統的吞吐率。但隨著硬體水平的提升如25G/100G網路和RDMA等新技術的出現,分散式檔案系統也有了質的飛躍,例如集團盤古2.0等系統為低延時高可靠的儲存提供很好的儲存平臺。
2.1 Swift系統結構
Swift訊息系統是在計算與儲存分離上的一次嘗試。它主要有以下特點:
首先,Swift的每個計算結點都是無狀態的,即每個worker上除log記錄,不儲存任何訊息系統相關資料。在swift訊息系統中,系統的狀態資料儲存在zookeeper上,訊息的內容則儲存在分散式檔案系統如HDFS, PANGU等上。
其次,Swift的每個計算結點都是等價的,只要訊息系統需要計算資源,就可以通過排程系統不停的申請並提升整個訊息系統的服務能力。目前Swift可以跑在Hippo或者Yarn上面。 Swift訊息系統每次申請的資源粒度也比較小,可以充當排程系統的碎片利用者。
最後,Swift自身的client與server的訊息讀寫協議,能夠保證訊息高效可靠的傳遞。
圖 1 SWIFT系統結構圖
圖1是SWIFT系統結構,其主要分成2種worker: Admin和Broker。Admin和Broker的資源分配與啟動都是基於排程系統。目前支援Hippo與Yarn這兩種排程系統,這2種worker都會有很多個例項,Broker worker都是等價的,Admin worker則有一個leader,其餘的等價,這些worker一般在Docker容器中工作。
Admin角色主要負責:1. Topic的增刪改 2. Topic對應物理partition與broker排程 3. Client讀寫資料時物理partition的定位。4.資源的調整,如broker個數的增減等。
Broker角色主要負責:1.partiton相關的訊息的讀寫 2. Partition相關資料的管理如過期資料的清理等。
2.2 Swift Topic介紹
Swift系統中的topic與其它訊息系統的類似,它是一堆相關訊息的集合,通常由業務自定義。如圖二所示,在swift中topic是由65536個邏輯分割槽組成,編號是[0 – 65535]。在Swift訊息系統內部,topic是由partition組成的,每個partition負責一個range的邏輯partition讀寫。
在使用者層面,使用者看不到Swift的物理partition,寫訊息時要麼需要提供一個hash欄位(由swift client自動對映到相應的邏輯分割槽)要麼提供一個0-65535的邏輯編號。 swift根據topic下每個partition的服務range,把訊息寫入相應partition的writer中。Writer可以通過同步與非同步方式把訊息append到對應的物理partition中。
Topic裡物理Partition個數的多少影響整個topic的讀寫能力,通過邏輯partition與物理partition對映,當topic的服務能力不足時,可以動態的擴充套件物理partition來提升讀寫能力。另外,物理partition是Swift的基本排程單元,admin會根據每個broker worker負載,儘可以平衡的排程partition。
圖 2 swift topic資料寫入示意圖
3. 可靠訊息讀寫機制
先前提到傳統的訊息系統為了保證訊息的可靠性,在寫訊息時需要先落盤,以防機器掛掉時,訊息不丟失。Swift也提供類似的模式,但落盤的物件是分散式檔案系統如HDFS。這種模式下正常寫落盤訊息延時的毫秒級,當HDFS壓力大時,會變成秒級,所以其效能不太穩定。Swift 設計了一種client與broker之間,broker與HDFS之間的訊息寫入與確認協議來保證訊息高效可靠的寫入與持久化,其機制類似TCP的滑動視窗協議。
圖3是訊息非同步安全傳送的示意圖。Broker在分配到partition進行服務時,會生成一個標記,其由partition的版本號(V),broker載入partition時間戳(S)以及訊息持久化的checkpoint (C)組成。Client在向admin定位到partition所在broker的時也會獲取partition的版本號(V)。版本號V主要在topic屬性發生變化時(例如partition的個數等)會更新。時間戳每次partition發生重載入或排程都會發生變化。
圖 3 SWIFT非同步安全傳送訊息示意圖
非同步安全寫訊息工作流程如下:
1. 使用者通過客戶端寫入一條訊息,client定位到寫哪個物理partition,同時把訊息寫入到對應的buffer中。使用者寫訊息時,還可以給每條訊息設定一個遞增編號,swift client會自動對映寫訊息進度與編號的關係。在非同步模式的,client會有專門的提交執行緒與broker進行通訊。
2. Client第一次向partition傳送訊息時,broker會驗證partition的版本V0, 匹配後才會接受訊息,同時會把三元組(V,S, C)返回。client收到accept訊息後,會更新已接受訊息的游標和協議的三元組資訊。
3. 客戶端可以持續的寫入訊息,同時broker那能partition中的訊息做非同步持久化,當持久化成功時,會更新持久化資訊(Ca)。持久化成功的訊息在記憶體中不會馬上刪除,只有記憶體不足時才會被回收。
4. Client的後臺傳送執行緒繼續工作,傳送訊息b,同時請求帶上了(V0,S0)。
5. Broker端驗證(V0,S0),收受訊息b,順便把持久化資訊也返回(V0,S0,Ca), client接收到accept資訊後,更新已傳送的游標到b,同時更新已接受的游標到a。訊息a已經持久化成功,在使用的記憶體將會被writer回收。Writer更新checkpoint (Ca)給使用者層,表示訊息a已經持久化。
6. 同3一樣,client繼續寫訊息c,broker繼續持久化訊息b。
7. 此時partition發生了排程(例如被分配到了其它機器),其HDFS上的檔案訊息馬上可以讀取到,但記憶體中的訊息會被清空。此時partition載入時間戳變成了S1。Client向admin重新定位到partition的服務broker寫入的訊息c和(V0,S0)。
8. Broker檢查client傳送的(V0,S0)與自身的(V0,S1)不相等,將拒絕此次訊息的寫入。主要基於訊息在partition內要求保序考慮。此時client還不知道b是否被序列化成功,partition重新被載入b是否被序列化成功的資訊也會被丟棄(無狀態),所以它也不知道。因Broker返回(V0,S1,C0),要求client重新傳送未持久化的所有訊息。
9. Client 重置已傳送游標到b之前,更新S1並重新傳送訊息b和c。
10. Broker檢驗client的(V0,S1)並收受訊息b和c,這時訊息b會被再次持久化化到HDFS上。Client重新更新已傳送游標到c。如果此後無新訊息的寫入,且buffer中的訊息還有未被持久化的,client會發起一次空寫操作獲取最新的持久化資訊。
步驟1-10是非同步訊息寫入的工作方式,使用者層可以獲取到當前持久化訊息的checkpoint,可以自己記錄傳送進度以便回滾。如果不方便記錄傳送進度,可以在寫完一段資料後,呼叫flush方法強制把資料從client的buffer放到broker的buffer中。此時訊息雖然沒有被持久化,但在client與partition各存一份。所以只有在broker與client同時掛掉才出現訊息丟失,因此我們認為這種方法也是比較安全的。
Swift partition的寫buffer快取所有寫入的訊息,只有當空間不足時,訊息記憶體空間才會被回收。對檔案上的訊息讀取,也會以塊buffer的方式做快取。Partition之間的buffer各檔案cache buffer都是共享儲存,由統一的記憶體回收模組管理。其保證冷門的partition基本不消耗資源,熱門的partition可以充分利用資源。正常情況下,swift的記憶體可以快取數分鐘的訊息,所以消費訊息時基本上從記憶體讀取,讀的效能也會很高效。在這個協議下,分散式檔案系統偶爾抖動也不會影響訊息的時效性,實際上檔案系統在數分鐘內的掛機也不影響訊息的實時傳遞。
4. Swift IN雙十一
2017年swift訊息系統開始在搜尋事業部與計算平臺事業部大規模應用,主要場景除主搜尋外,還包括Porsche,K-monitor,IGraph, DII, OpenSearch,RankService等業務。另外,Swift在螞蟻金服,阿里媽媽和神馬事業部也有多套swift機群的部署。
雙十一當天,同時服務的topic個數均值近萬個, partition個數達10萬。當天建立與刪除的topic近2萬個,其主要來自IGRAPH, RankService,DII等業務索引的重建,平時也差不多是這個數量級。 當天Swift訊息系統總共寫入數萬億條訊息,讀取數十萬億條訊息,讀寫比3:1。總讀寫訊息內容位元組大小數PB,訊息的內容是經過Swift client壓縮,一般訊息壓縮率是原始大小的1/4 – 1/2之間。讀寫的最大QPS與均值都超億條/秒,讀寫請求的峰值與均值超千萬次/秒。線上與離線讀寫訊息的worker超20萬個。 另外,swift日常處理的資料與雙十一的數值相差不大。
5. 總結與展望
Swift訊息系統經過一年多的不斷改進與優化,目前每天能處理PB級與萬億級的訊息,但在不久的將來還需要解一些問題:
1. 超大量client如百萬級的client寫入,涉及到的partition定位與worker的連線問題。當client達百萬時,首先碰到的一個問題是連線數不夠用,目前離線的一個client寫資料會對所有相關載入partition的worker產生連線,如果worker有N個,partition有M個,其連線數達N*M個。其次partition發生排程時,partition的定位瞬間能打爆Admin。
2.每秒百億級別的訊息讀寫時,如何減少系統處理訊息量。Swift目前有client主動合併訊息的優化,但能合併的訊息數量並不多,能否在broker端進行訊息合併與儲存。在大規模訊息讀寫時如何降低對HDFS的壓力。Swift目前提供記憶體topic等來儘可能的減少訊息落盤,是否有更好的機制也需要探索。
6. 相關職位招聘
釋出時間: | 2017-11-17 | 工作地點: | 杭州市 | 工作年限: | 二年以上 |
所屬部門: | 搜尋事業部 | 學 歷: | 本科 | 招聘人數: | 3 |
崗位描述:
參與阿里巴巴集團內部實時訊息系統開發,支援每秒萬億級別訊息讀寫,提供高可靠、高效能、高伸縮、低延時的服務,支撐電商、金融、物流、文娛、大資料、人工智慧、搜尋、廣告等各種業務場景。
崗位要求:
1. 精通C/C++語言和資料結構,演算法和資料結構基礎紮實
2. 學習能力較強,有很好的邏輯思維能力,善於主動思考,對技術有強烈激情
3. 具有優秀的分析和解決實際問題的能力和態度,追求編寫優雅的程式碼,從技術趨勢和思路上能影響技術團隊;
4. 符合以下條件之一者優先。
(1) 有網際網路中介軟體(資料、訊息、服務等)開發經驗者優先。
(2) 對hbase/hadoop/cassandra/elasticsearch/rocksdb等開源儲存產品的一種或多種熟悉者優先
(3) 對linux核心原理或伺服器硬體熟悉者優先
相關文章
- 計算儲存分離在訊息佇列上的應用佇列
- 線上課程|儲存與計算分離,京東在Elasticsearch上的實踐分享Elasticsearch
- 容器化RDS—— 計算儲存分離 or 本地儲存
- 計算儲存分離在京東雲訊息中介軟體JCQ上的應用
- 搜尋線上服務的儲存計算分離
- Shopee ClickHouse 冷熱資料分離儲存架構與實踐架構
- Flink 2.0 狀態存算分離改造實踐
- 儲存系統設計指南之儲存分類
- 系統設計實踐(02)- 文字儲存服務
- 電商非同步訊息系統的實踐非同步
- 高效能分散式計算與儲存系統設計概要分散式
- vivo 軒轅檔案系統:AI 計算平臺儲存效能最佳化實踐AI
- IM開發乾貨分享:淺談IM系統中離線訊息、歷史訊息的最佳實踐
- 大型系統儲存層遷移實踐
- 現代IM系統中訊息推送和儲存架構的實現架構
- Swift實踐:使用CoreData儲存多種資料類的通訊錄Swift
- 【RocketMQ】訊息的儲存MQ
- TKE使用者故事 | 作業幫檢索服務基於Fluid的計算儲存分離實踐UI
- IM系統海量訊息資料是怎麼儲存的?
- 仿微博訊息中心的系統設計與實現
- 分散式系統中資料儲存方案實踐分散式
- 容器化RDS|計算儲存分離架構下的 IO 優化架構優化
- 分散式高效能訊息系統(Kafka MQ)的原理與實踐分散式KafkaMQ
- 計算機的硬體系統儲存器計算機
- RocksDB 在 vivo 訊息推送系統中的實踐
- 面向不同需求的物件儲存系統對比:Ceph與Swift物件Swift
- Kafka 訊息儲存機制Kafka
- 6月2日雲棲精選夜讀:儲存與計算分離:OSS構建表+計算引擎對接
- 容器化RDS—計算儲存分離架構下的“Split-Brain”架構AI
- 分散式塊儲存系統Ursa的設計與實現分散式
- vivo全球商城:庫存系統架構設計與實踐架構
- 在spring boot中訊息推送系統設計與實現Spring Boot
- 分散式儲存系統的最佳實踐:系統發展路徑分散式
- RocketMQ 原理:訊息儲存、高可用、訊息重試、訊息冪等性MQ
- RocketMQ -- 訊息傳送儲存流程MQ
- Kafka -- 訊息傳送儲存流程Kafka
- 使用mongodb、Kafka儲存mqtt訊息MongoDBKafkaMQQT
- 儲存系統實現-構建自己的儲存系統(一)