基於SSD的Kafka應用層緩存架構設計與實現

Kafka在美團數據平臺的現狀

Kafka出色的I/O優化以及多處異步化設計,相比其餘消息隊列系統具備更高的吞吐,同時可以保證不錯的延遲,十分適合應用在整個大數據生態中。html

目前在美團數據平臺中,Kafka承擔着數據緩衝和分發的角色。以下圖所示,業務日誌、接入層Nginx日誌或線上DB數據經過數據採集層發送到Kafka,後續數據被用戶的實時做業消費、計算,或通過數倉的ODS層用做數倉生產,還有一部分則會進入公司統一日誌中心,幫助工程師排查線上問題。git

目前美團線上Kafka規模:github

  • 集羣規模:節點數達6000+,集羣數100+。
  • 集羣承載:Topic數6萬+,Partition數41萬+。
  • 處理的消息規模:目前天天處理消息總量達8萬億,峯值流量爲1.8億條/秒
  • 提供的服務規模:目前下游實時計算平臺運行了3萬+做業,而這其中絕大多數的數據源均來自Kafka。

Kafka線上痛點分析&核心目標

當前Kafka支撐的實時做業數量衆多,單機承載的Topic和Partition數量很大。這種場景下很容易出現的問題是:同一臺機器上不一樣Partition間競爭PageCache資源,相互影響,致使整個Broker的處理延遲上升、吞吐降低。算法

接下來,咱們將結合Kafka讀寫請求的處理流程以及線上統計的數據來分析一下Kafka在線上的痛點。後端

原理分析

Kafka處理讀寫流程的示意圖

對於Produce請求:Server端的I/O線程統一將請求中的數據寫入到操做系統的PageCache後當即返回,當消息條數到達必定閾值後,Kafka應用自己或操做系統內核會觸發強制刷盤操做(如左側流程圖所示)。緩存

對於Consume請求:主要利用了操做系統的ZeroCopy機制,當Kafka Broker接收到讀數據請求時,會向操做系統發送sendfile系統調用,操做系統接收後,首先試圖從PageCache中獲取數據(如中間流程圖所示);若是數據不存在,會觸發缺頁異常中斷將數據從磁盤讀入到臨時緩衝區中(如右側流程圖所示),隨後經過DMA操做直接將數據拷貝到網卡緩衝區中等待後續的TCP傳輸。微信

綜上所述,Kafka對於單一讀寫請求均擁有很好的吞吐和延遲。處理寫請求時,數據寫入PageCache後當即返回,數據經過異步方式批量刷入磁盤,既保證了多數寫請求都能有較低的延遲,同時批量順序刷盤對磁盤更加友好。處理讀請求時,實時消費的做業能夠直接從PageCache讀取到數據,請求延遲較小,同時ZeroCopy機制可以減小數據傳輸過程當中用戶態與內核態的切換,大幅提高了數據傳輸的效率。架構

但當同一個Broker上同時存在多個Consumer時,就可能會因爲多個Consumer競爭PageCache資源致使它們同時產生延遲。下面咱們以兩個Consumer爲例詳細說明:併發

如上圖所示,Producer將數據發送到Broker,PageCache會緩存這部分數據。當全部Consumer的消費能力充足時,全部的數據都會從PageCache讀取,所有Consumer實例的延遲都較低。此時若是其中一個Consumer出現消費延遲(圖中的Consumer Process2),根據讀請求處理流程可知,此時會觸發磁盤讀取,在從磁盤讀取數據的同時會預讀部分數據到PageCache中。當PageCache空間不足時,會按照LRU策略開始淘汰數據,此時延遲消費的Consumer讀取到的數據會替換PageCache中實時的緩存數據。後續當實時消費請求到達時,因爲PageCache中的數據已被替換掉,會產生預期外的磁盤讀取。這樣會致使兩個後果:異步

  1. 消費能力充足的Consumer消費時會失去PageCache的性能紅利。
  2. 多個Consumer相互影響,預期外的磁盤讀增多,HDD負載升高。

咱們針對HDD的性能和讀寫併發的影響作了梯度測試,以下圖所示:

能夠看到,隨着讀併發的增長,HDD的IOPS和帶寬均會明顯降低,這會進一步影響整個Broker的吞吐以及處理延遲。

線上數據統計

目前Kafka集羣TP99流量在170MB/s,TP95流量在100MB/s,TP50流量爲50-60MB/s;
單機的PageCache平均分配爲80GB,取TP99的流量做爲參考,在此流量以及PageCache分配狀況下,PageCache最大可緩存數據時間跨度爲80*1024/170/60 = 8min,可見當前Kafka服務總體對延遲消費做業的容忍性極低。該狀況下,一旦部分做業消費延遲,實時消費做業就可能會受到影響。

同時,咱們統計了線上實時做業的消費延遲分佈狀況,延遲範圍在0-8min(實時消費)的做業只佔80%,說明目前存在線上存在20%的做業處於延遲消費的狀態。

痛點分析總結

總結上述的原理分析以及線上數據統計,目前線上Kafka存在以下問題:

  1. 實時消費與延遲消費的做業在PageCache層次產生競爭,致使實時消費產生非預期磁盤讀。
  2. 傳統HDD隨着讀併發升高性能急劇降低。
  3. 線上存在20%的延遲消費做業。

按目前的PageCache空間分配以及線上集羣流量分析,Kafka沒法對實時消費做業提供穩定的服務質量保障,該痛點亟待解決。

預期目標

根據上述痛點分析,咱們的預期目標爲保證明時消費做業不會因爲PageCache競爭而被延遲消費做業影響,保證Kafka對實時消費做業提供穩定的服務質量保障。

解決方案

爲何選擇SSD

根據上述緣由分析可知,解決目前痛點可從如下兩個方向來考慮:

  1. 消除實時消費與延遲消費間的PageCache競爭,如:讓延遲消費做業讀取的數據不回寫PageCache,或增大PageCache的分配量等。
  2. 在HDD與內存之間加入新的設備,該設備擁有比HDD更好的讀寫帶寬與IOPS。

對於第一個方向,因爲PageCache由操做系統管理,若修改其淘汰策略,那麼實現難度較爲複雜,同時會破壞內核自己對外的語義。另外,內存資源成本較高,沒法進行無限制的擴展,所以須要考慮第二個方向。

SSD目前發展日益成熟,相較於HDD,SSD的IOPS與帶寬擁有數量級級別的提高,很適合在上述場景中當PageCache出現競爭後承接部分讀流量。咱們對SSD的性能也進行了測試,結果以下圖所示:

從圖中能夠發現,隨着讀取併發的增長,SSD的IOPS與帶寬並不會顯著下降。經過該結論可知,咱們可使用SSD做爲PageCache與HDD間的緩存層。

架構決策

在引入SSD做爲緩存層後,下一步要解決的關鍵問題包括PageCache、SSD、HDD三者間的數據同步以及讀寫請求的數據路由等問題,同時咱們的新緩存架構須要充分匹配Kafka引擎讀寫請求的特徵。本小節將介紹新架構如何在選型與設計上解決上述提到的問題。

Kafka引擎在讀寫行爲上具備以下特性:

  • 數據的消費頻率隨時間變化,越久遠的數據消費頻率越低。
  • 每一個分區(Partition)只有Leader提供讀寫服務。
  • 對於一個客戶端而言,消費行爲是線性的,數據並不會重複消費。

下文給出了兩種備選方案,下面將對兩種方案給出咱們的選取依據與架構決策。

備選方案一:基於操做系統內核層實現

目前開源的緩存技術有FlashCache、BCache、DM-Cache、OpenCAS等,其中BCache和DM-Cache已經集成到Linux中,但對內核版本有要求,受限於內核版本,咱們僅能選用FlashCache/OpenCAS。

以下圖所示,FlashCache以及OpenCAS兩者的核心設計思路相似,兩種架構的核心理論依據爲「數據局部性」原理,將SSD與HDD按照相同的粒度拆成固定的管理單元,以後將SSD上的空間映射到多塊HDD層的設備上(邏輯映射or物理映射)。在訪問流程上,與CPU訪問高速緩存和主存的流程相似,首先嚐試訪問Cache層,若是出現CacheMiss,則會訪問HDD層,同時根據數據局部性原理,這部分數據將回寫到Cache層。若是Cache空間已滿,會經過LRU策略替換部分數據。

FlashCache/OpenCAS提供了四種緩存策略:WriteThrough、WriteBack、WriteAround、WriteOnly。 因爲第四種不作讀緩存,這裏咱們只看前三種。

寫入:

  • WriteThrough:數據寫操做在寫入SSD的同時會寫入到後端存儲。
  • WriteBack:數據寫操做僅寫入SSD即返回,由緩存策略flush到後臺存儲。
  • WriteAround:數據寫入操做直接寫入後端存儲,同時SSD對應的緩存會失效。

讀取:

  • WriteThrough/WriteBack/WriteAround:首先讀取SSD,命中不了的將再次讀取後端存儲,並數據會被刷入到SSD緩存中。

更多詳細實現細節,極大可參見這兩者的官方文檔:

備選方案二:Kafka應用內部實現

上文提到的第一類備選方案中,核心的理論依據「數據局部性」原理與Kafka的讀寫特性並不能徹底吻合,「數據回刷」這一特性依然會引入緩存空間污染問題。同時,上述架構基於LRU的淘汰策略也與Kafka讀寫特性存在矛盾,在多Consumer併發消費時,LRU淘汰策略可能會誤淘汰掉一些近實時數據,致使實時消費做業出現性能抖動。

可見,備選方案一併不能徹底解決當前Kafka的痛點,須要從應用內部進行改造。總體設計思路以下,將數據按照時間維度分佈在不一樣的設備中,近實時部分的數據緩存在SSD中,這樣當出現PageCache競爭時,實時消費做業從SSD中讀取數據,保證明時做業不會受到延遲消費做業影響。下圖展現了基於應用層實現的架構處理讀請求的流程:

當消費請求到達Kafka Broker時,Kafka Broker直接根據其維護的消息偏移量(Offset)和設備的關係從對應的設備中獲取數據並返回,而且在讀請求中並不會將HDD中讀取的數據回刷到SSD,防止出現緩存污染。同時訪問路徑明確,不會因爲Cache Miss而產生的額外訪問開銷。

下表對不一樣候選方案進行了更加詳細的對比:

最終,結合與Kafka讀寫特性的匹配度,總體工做量等因素綜合考慮,咱們採用Kafka應用層實現這一方案,由於該方案更貼近Kafka自己讀寫特性,能更加完全地解決Kafka的痛點。

新架構設計

概述

根據上文對Kafka讀寫特性的分析,咱們給出應用層基於SSD的緩存架構的設計目標:

  • 數據按時間維度分佈在不一樣的設備上,近實時數據分佈在SSD上,隨時間的推移淘汰到HDD上。
  • Leader分區中全部數據均寫入SSD中。
  • 從HDD中讀取的數據不回刷到SSD中。

依據上述目標,咱們給出應用層基於SSD的Kafka緩存架構實現:

Kafka中一個Partition由若干LogSegment構成,每一個LogSegment包含兩個索引文件以及日誌消息文件。一個Partition的若干LogSegment按Offset(相對時間)維度有序排列。

根據上一小節的設計思路,咱們首先將不一樣的LogSegment標記爲不一樣的狀態,如圖所示(圖中上半部分)按照時間維度分爲OnlyCache、Cached以及WithoutCache三種常駐狀態。而三種狀態的轉換以及新架構對讀寫操做的處理如圖中下半部分所示,其中標記爲OnlyCached狀態的LogSegment只存儲在SSD上,後臺線程會按期將Inactive(沒有寫流量)的LogSegment同步到SSD上,完成同步的LogSegment被標記爲Cached狀態。最後,後臺線程將會按期檢測SSD上的使用空間,當空間達到閾值時,後臺線程將會按照時間維度將距離如今最久的LogSegment從SSD中移除,這部分LogSegment會被標記爲WithoutCache狀態。

對於寫請求而言,寫入請求依然首先將數據寫入到PageCache中,知足閾值條件後將會刷入SSD。對於讀請求(當PageCache未獲取到數據時),若是讀取的offset對應的LogSegment的狀態爲Cached或OnlyCache,則數據從SSD返回(圖中LC2-LC1以及RC1),若是狀態爲WithoutCache,則從HDD返回(圖中LC1)。

對於Follower副本的數據同步,可根據Topic對延遲以及穩定性的要求,經過配置決定寫入到SSD仍是HDD。

關鍵優化點

上文介紹了基於SSD的Kafka應用層緩存架構的設計概要以及核心設計思路,包括讀寫流程、內部狀態管理以及新增後臺線程功能等。本小節將介紹該方案的關鍵優化點,這些優化點均與服務的性能息息相關。主要包括LogSegment同步以及Append刷盤策略優化,下面將分別進行介紹。

LogSegment同步

LogSegment同步是指將SSD上的數據同步到HDD上的過程,該機制在設計時主要有如下兩個關鍵點:

  1. 同步的方式:同步方式決定了HDD上對SSD數據的可見時效性,從而會影響故障恢復以及LogSegment清理的及時性。
  2. 同步限速:LogSegment同步過程當中經過限速機制來防止同步過程當中對正常讀寫請求形成影響

同步方式

關於LogSegment的同步方式,咱們給出了三種備選方案,下表列舉了三種方案的介紹以及各自的優缺點:

最終,咱們對一致性維護代價、實現複雜度等因素綜合考慮,選擇了後臺同步Inactive的LogSegment的方式。

同步限速

LogSegment同步行爲本質上是設備間的數據傳輸,會同時在兩個設備上產生額外的讀寫流量,佔用對應設備的讀寫帶寬。同時,因爲咱們選擇了同步Inactive部分的數據,須要進行整段的同步。若是在同步過程當中不加以限制會對服務總體延遲形成較大的影響,主要表如今下面兩個方面:

  • 從單盤性能角度,因爲SSD的性能遠高於HDD,所以在數據傳輸時,HDD寫入帶寬會被寫滿,此時其餘的讀寫請求會出現毛刺,若是此時有延遲消費從HDD上讀取數據或者Follower正在同步數據到HDD上,會形成服務抖動。
  • 從單機部署的角度,單機會部署2塊SSD與10塊HDD,所以在同步過程當中,1塊SSD須要承受5塊HDD的寫入量,所以SSD一樣會在同步過程當中出現性能毛刺,影響正常的請求響應延遲。

基於上述兩點,咱們須要在LogSegment同步過程當中增長限速機制,整體的限速原則爲在不影響正常讀寫請求延遲的狀況下儘量快速地進行同步。由於同步速度過慢會致使SSD數據沒法被及時清理而最終被寫滿。同時爲了能夠靈活調整,該配置也被設置爲單Broker粒度的配置參數。

日誌追加刷盤策略優化

除了同步問題,數據寫入過程當中的刷盤機制一樣影響服務的讀寫延遲。該機制的設計不只會影響新架構的性能,對原生Kafka一樣會產生影響。

下圖展現了單次寫入請求的處理流程:

在Produce請求處理流程中,首先根據當前LogSegment的位置與請求中的數據信息肯定是否須要滾動日誌段,隨後將請求中的數據寫入到PageCache中,更新LEO以及統計信息,最後根據統計信息肯定是否須要觸發刷盤操做,若是須要則經過fileChannel.force強制刷盤,不然請求直接返回。

在整個流程中,除日誌滾動與刷盤操做外,其餘操做均爲內存操做,不會帶來性能問題。日誌滾動涉及文件系統的操做,目前,Kafka中提供了日誌滾動的擾動參數,防止多個Segment同時觸發滾動操做給文件系統帶來壓力。針對日誌刷盤操做,目前Kafka給出的機制是以固定消息條數觸發強制刷盤(目前線上爲50000),該機制只能保證在入流量必定時,消息會以相同的頻率刷盤,但沒法限制每次刷入磁盤的數據量,對磁盤的負載沒法提供有效的限制。

以下圖所示,爲某磁盤在午高峯時間段write_bytes的瞬時值,在午高峯時間段,因爲寫入流量的上升,在刷盤過程當中會產生大量的毛刺,而毛刺的值幾乎接近磁盤最大的寫入帶寬,這會使讀寫請求延遲發生抖動。

針對該問題,咱們修改了刷盤的機制,將本來的按條數限制修改成按實際刷盤的速率限制,對於單個Segment,刷盤速率限制爲2MB/s。該值考慮了線上實際的平均消息大小,若是設置太小,對於單條消息較大的Topic會過於頻繁的進行刷新,在流量較高時反而會加劇平均延遲。目前該機制已在線上小範圍灰度,右圖展現了灰度後同時間段對應的write_bytes指標,能夠看到相比左圖,數據刷盤速率較灰度前明顯平滑,最高速率僅爲40MB/s左右。

對於SSD新緩存架構,一樣存在上述問題,所以在新架構中,在刷盤操做中一樣對刷盤速率進行了限制。

方案測試

測試目標

  • 驗證基於應用層的SSD緩存架構可以避免實時做業受到延遲做業的影響。
  • 驗證相比基於操做系統內核層實現的緩存層架構,基於應用層的SSD架構在不一樣流量下讀寫延遲更低。

測試場景描述

  • 構建4個集羣:新架構集羣、普通HDD集羣、FlashCache集羣、OpenCAS集羣。
  • 每一個集羣3個節點。
  • 固定寫入流量,比較讀、寫耗時。
  • 延遲消費設置:只消費相對當前時間10~150分鐘的數據(超過PageCache的承載區域,不超過SSD的承載區域)。

測試內容及重點關注指標

  • Case1: 僅有延遲消費時,觀察集羣的生產和消費性能。

    • 重點關注的指標:寫耗時、讀耗時,經過這2個指標體現出讀寫延遲。
    • 命中率指標:HDD讀取量、HDD讀取佔比(HDD讀取量/讀取總量)、SSD讀取命中率,經過這3個指標體現出SSD緩存的命中率。
  • Case2: 存在延遲消費時,觀察實時消費的性能。

    • 重點指標:實時做業的SLA(服務質量)的5個不一樣時間區域的佔比狀況。

測試結果

從單Broker請求延遲角度看:

在刷盤機制優化前,SSD新緩存架構在全部場景下,較其餘方案都具備明顯優點。

刷盤機制優化後,其他方案在延遲上服務質量有提高,在較小流量下因爲flush機制的優化,新架構與其餘方案的優點變小。當單節點寫入流量較大時(大於170MB)優點明顯。

從延遲做業對實時做業的影響方面看:

新緩存架構在測試所涉及的全部場景中,延遲做業都不會對實時做業產生影響,符合預期。

總結與將來展望

Kafka在美團數據平臺承擔統一的數據緩存和分發的角色,針對目前因爲PageCache互相污染、進而引起PageCache競爭致使實時做業被延遲做業影響的痛點,咱們基於SSD自研了Kafka的應用層緩存架構。本文主要介紹Kafka新架構的設計思路以及與其餘開源方案的對比。與普通集羣相比,新緩存架構具有很是明顯的優點:

  1. 下降讀寫耗時:比起普通集羣,新架構集羣讀寫耗時下降80%。
  2. 實時消費不受延遲消費的影響:比起普通集羣,新架構集羣實時讀寫性能穩定,不受延時消費的影響。

目前,這套緩存架構優已經驗證完成,正在灰度階段,將來也優先部署到高優集羣。其中涉及的代碼也將提交給Kafka社區,做爲對社區的回饋,也歡迎你們跟咱們一塊兒交流。

做者簡介

世吉,仕祿,均爲美團數據平臺工程師。

| 想閱讀更多技術文章,請關注美團技術團隊(meituantech)官方微信公衆號。

| 在公衆號菜單欄回覆【2019年貨】、【2018年貨】、【2017年貨】、【算法】等關鍵詞,可查看美團技術團隊歷年技術文章合集。

相關文章
相關標籤/搜索