天天看點

幹貨 | 金融級消息隊列的演進 — 螞蟻金服的實踐之路 小螞蟻說:

幹貨 | 金融級消息隊列的演進 — 螞蟻金服的實踐之路 小螞蟻說:

小螞蟻說:

消息隊列作為一個資料的集散中心,承載了越來越多的場景和資料,從最開始的 OLTP 到 OLAP,甚至再到物聯網、人工智能、機器學習等場景,都有很大的想像空間。 在能力上,消息隊列現在擁有了資料,擁有了算力,從承載資料走到了解資料。

螞蟻金服也在思考給消息隊列加入算法的能力,讓算法走進消息隊列,走向下一個階段 :洞察資料。把這些能力綜合起來,打造一個智慧的傳輸計算服務平台。

還有一個好消息,消息隊列作為 SOFA (Scalable Open Financial Architecture )技術體系比較核心的組成部分,後續也會積極擁抱開源和社群。

本文根據蔣濤在 GIAC 2018 的主題分享《金融級消息隊列的演進之路》整理編輯,将給大家分享螞蟻金服消息隊列發展過程中的故事,以及這個過程中的架構思考。

金融場景下的消息系統的關鍵需求

在螞蟻金服,消息隊列已經有十多年的曆史了。在07、08年時,我們采用了 ESB 這樣的方式來實作消息的機制。

那個時候遇到的最頭疼的問題就是丢消息,排查和修複起來非常的痛苦。到了09年,和淘寶共建并上線了新的消息隊列系統,丢消息的問題得到了有效的改善。

螞蟻的業務具有金融級的屬性,從這個角度,有哪些比較關鍵的需求呢? 集中表現為以下四點:

  1. 極高的可靠性
  2. 舉個例子,通過消息去生成賬單,如果這個消息不可靠,消息丢了,這個時候會發生什麼樣的情況呢?客戶付了一筆錢,但是在賬單或者消費記錄裡卻看不到這筆記錄,這個時候就非常困惑了。 是以極高的可靠性指的是:消息不能丢。
  3. 極強的一緻性
  4. 極強的一緻性在金融業務當中是非常關鍵和重要的。 假如做一筆轉賬操作,因為種種原因,比如網絡抖動,轉賬失敗了,如果一緻性沒有做好,可能還會收到一條做了一筆轉賬的通知,這個時候系統的資料就不一緻了。
  5. 持續的可用性
  6. 持續的可用性,是指在希望用系統提供的服務能力的時候,這個服務一定是要可用的。 比如說雙十一的時候,線上生成一筆訂單需要支付,一定希望它能非常順利的支付完成。再一個,現線上下的場景非常火,到超市去買東西,結賬的時候也希望掃碼支付要非常順暢,這都是對可用性的要求。
  7. 極高的性能
  8. 在螞蟻金服,每天有千億級的消息在流轉,峰值的 TPS 也達到了千萬級。在這麼大的體量下,對性能的要求是非常高的。另外,從成本角度和使用者的體驗的角度,性能也是非常需要關注的地方。

對比經典的消息系統,需要建立哪些機制來滿足以上的關鍵需求?

剛剛提到了金融場景下的四個核心的性能要求,那麼具體如何來滿足呢?

1. 如何做到極高的可靠性?

  • ACK 的機制。ACK 機制借鑒了 TCP 裡面的思路,通過發送階段、持久化階段、投遞階段的 ACK 機制,保證了消息在流轉路徑的各個環節上的可靠性。
  • 重試的機制,保證了消息在投遞出去後,當消費端消費不成功的時候,還可以再次去消費。
  • 通過存儲層的持久化機制和可靠性機制來保證消息資料本身的可靠性。

2. 采用兩階段事務消息機制來保證極強的一緻性

在第一階段裡面,把發消息和業務自己的業務操作放到本地事務中,發出來的是帶有未送出狀态的消息。 在第二階段,會根據本地事務執行的情況來決定一階段發出來的消息是送出還是復原,如果是復原,把消息删掉就好了,如果是送出,會去更新這個消息的狀态,從未送出改成已送出,接着去做投遞的動作。

如果第二階段中的事務狀态通知丢失了,消息服務端會去主動向消息發送端做事務狀态回查,直到拿到明确的事務送出或者復原的回查結果。

3. 持續的可用性的實作

在單機房的時代就在做提升可用性的事情。比如,在應用層面做了線程池的隔離,做了限流、熔斷等等。在架構層面去做各種水準伸縮能力,在故障隔離層面做單點的隔離,做叢集部署的隔離等等。這些手段提高了系統的可用性。

但是,由于受限于單機房部署的架構,當出現機房級别問題的時候,前面的手段就心有餘而力不足了。

當然,同城雙活架構可以通過業務流量在兩個機房之間做切換,也可以通過資料層面的切換等手段來有效的解決機房單點的問題。

但是,随着業務增長,同城雙機房模式在容量和容災能力上也逐漸無法滿足業務發展需求了。

面對同城雙活也無法解決的情況,螞蟻金服沉澱出異地多活 LDC 架構:

在 LDC 架構下,對消息隊列有怎樣的需求?

以轉賬為例,在異地多活的架構下,收款方跟轉賬人可能在一個邏輯 Zone 裡面,也可能不在一個邏輯 Zone 裡面,甚至他們可能都不在一個城市。這樣帶來一個最重要、最核心的需求就是消息隊列需要具有非常靈活、非常強大的路由能力,可以做Zone内的路由,可以做同城跨Zone的路由,也可以做跨城跨 Zone 的路由。

在實作上,如果發現這個消息是要做同城跨 Zone 的路由,在消息服務端做了一個打通,通過服務端做轉發,當發現是跨城場景的時候,通過一個叫 MQ-router 的系統,對跨城的鍊路做了一個收斂,也對城市級部署的邏輯做了一個收口,所有需要經過跨城的邏輯全部收口到這樣一個系統當中,統一并靈活的支撐了異地多活的架構。

在 LDC 架構下面,消息有趣的應用場景

有一類會員資訊資料,比較有特點:

  1. 通路量非常大,把它放到緩存裡面,降低對後端資料庫的壓力。
  2. 在一次業務請求當中,對這個資料可能有非常多次的通路,是以對資料通路的延遲非常敏感。如果這類資料需要跨城才能通路到的話,跨城帶來的延時對業務而言是非常難以接受的。是以就要求這類資料從本城市就能夠通路到,每個城市都需要有全量的這類資料。
  3. 這類資料對變更的時效性非常敏感。資料變更了,需要非常快的感覺到。如果依靠資料庫層面的複制機制來做這件事情,會有大概秒級的延遲。

于是,我們設計了一個基于消息的方案,來實作一個城市級的緩存更新的機制。重點給 MQ-router 增加了廣播的能力。當這類資料發生變更的時候,以消息的方式發出來,通過 MQ-router 以廣播的形式發送到所有城市去,這樣就達到了多個城市的緩存實時更新的效果。

4. 性能方面是持續在打磨的一件事情

消息隊列基于 SEDA 模式來實作,引入了自研的高性能網絡通信層 SOFABolt來提高消息通信的性能。除此傳統的優化手段之外,也在調研和思考更先進的一些方式,比如硬體結合的方式,像DPDK、RDMA這樣的技術,去追求更極緻的性能。

擁抱大資料時代,我們做了拉模式的消息隊列

有很長一段時間,消息隊列的研發工作都是圍繞着交易、支付、賬務等OLTP的業務展開。是以一直在打磨消息隊列在OLTP場景下的功能。比如,通過資料庫存儲保證消息可靠性,通過推的模式提高消息的實時性等。 随着業務場景的擴充,特别是大資料時代的到來,越來越多的OLAP場景出現了。這個時候前面的這些做法,特别是推的這種模式就遇到很多的困難。

到了這個階段,我們去做了基于Log語義的拉模式的消息隊列。 拉模式消息部署在實體機上,通過順序寫本地磁盤的方式去實作拉的語義。在一定時間内比較有效的支援了OLAP這種場景的需求。

走向計算存儲分離的架構,從挂盤模式到 API 模式

随着拉模式的推廣,很多 OLTP 的場景也逐漸的采用了拉模式,提出了很多新的需求。比如 OLTP 對資料可靠性要求比較高,對本地檔案存儲可靠性的問題就非常關注。

由于是基于實體機部署,也遇到很多運維上的難點,比如成本、機型等等的一些問題。特别是實體機機型變化非常多,每次采購可能都不一樣,非常難以做标準化。在做容量規劃、縮容擴容這些事情時會遇到非常多的困難。

消息是比較重 IO 輕計算的模型,在實體機上就會表現出非常明顯的資源配比不均衡的問題。往往是磁盤已經不夠用了,但 CPU 還很空閑。基于實體機的運維也很複雜,資源使用率不高、容量規劃不好做、擴容縮容困難等問題凸顯。

在做這件事情的時候,我們一開始采取了一種比較輕量的方式,稱之為挂盤的模式。 通過挂載的方式,将分布式檔案系統挂在消息隊列應用上面。這個做法的好處是應用系統本身基本上不需要做什麼改造。消息資料透明的寫到了分布式檔案系統上,依靠分布式檔案系統提供的三副本高可靠的能力來保障消息資料的可靠性。

在這個階段還做了一件事情,就是把消息應用的規格做了标準化。可以去制定類似8C、16G、1T 這樣的規格,有了标準規格,就可以比較準确的測算某個規格可以頂多少TPS的消息量,這樣做容量規劃就很容易了。 這個模式上去之後,承載了一些業務,也接受了雙十一大促的考驗。

于是,我們開始了計算存儲分離的第二階段:API 模式,在性能上有了一個比較明顯的提升。 這個模式下,消息服務端要做比較大的改動,趁着這個機會,也做了很多功能方面的增強。比如,加入了對全局固定分區的支援,還有發送幂等與強順序的能力等。 同時,把資料落地也做了一個改變,原先資料全部集中在一個commit log中,轉移到了隊列裡面去。這樣帶來的好處是可以在隊列級别做更細粒度的配置和管控。

這個架構整體而言是一個相對比較完善的計算存儲分離的架構了。在應用層面也做了很多可擴充的設計。

整體上,計算存儲分離的模式給消息隊列打下比較好的基礎,可以跟螞蟻金服全站的運維模式做很好的适配。

讓計算走進消息隊列,賦予消息隊列計算能力

消息隊列承載了越來越多的消息資料,大量的資料流進來再流出去。都說在大資料時代,資料就是金錢,但是可以發現這麼多的資料流過消息隊列,卻沒有淘到金。

通過思考這個問題,發現非常關鍵的一點是因為一直在用一種比較傳統的方式去看待消息隊列,認為它是消息的一個通道,消息流進來再流出去,使命就結束了。在這樣的思路下,着力打造的是它的傳輸能力,它的存儲能力,它的可靠性等。但是卻忽略了在大資料時代非常重要的一個能力,就是計算的能力。

帶着這個問題去看業界的一些發展,得到了很多新的思路。特别是從Kafka身上得到了很多的啟發。

于是我們決定讓計算走進消息隊列,以 streaming 方式為消息隊列增加了一種計算能力,實作了一個輕量級的非中心式的計算架構,既可以嵌入用戶端,也可以嵌入消息的服務端,做一些輕量級的計算,支援一些比較通用和輕量的算子和多種計算視窗語義。

至此,消息隊列有了傳輸、存儲和計算的能力

基于這些能力,把消息隊列往更大的層面上去推進,建構一個資料傳輸計算平台。不斷豐富消息隊列能力,不斷拓展越來越豐富的資料源,擷取越來越多樣的資料,并且把消息投遞到更多的目的地去。在傳輸過程中對消息進行計算,以獲得更多計算帶來的價值。

總結

通過前面的回顧,我們可以看到,消息隊列作為一個資料的集散中心,承載了越來越多的場景和資料。

在能力上,消息隊列現在擁有了資料,擁有了算力,正在走過一條從承載資料到了解資料的道路。接下來,我們也在思考給消息隊列加入算法的能力,讓算法走進消息隊列。 這樣就可以向下一個階段 -- 洞察資料再邁出一步,就可以把這些能力綜合起來,去打造一個智慧的傳輸計算服務平台。這樣消息資料不僅是流轉過消息隊列,還可以經過更多的計算和加工,更輕快更實時的發揮更大的價值。

交流社群

我們也為對 SOFA 中間件感興趣的同學準備了微信的交流群,歡迎感興趣的同學添加加群小助手(微信号:Ant-Techfin01)加入我們 SOFA 交流群讨論和咨詢相關問題哦。

歡迎通路 http://github.com/alipay 了解更多 SOFA 開源資訊(也可閱讀原文檢視),共同打造SOFAStack 。更多最新分布式架構幹貨,請關注公衆号《金融級分布式架構

繼續閱讀