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

圖片描述

小螞蟻說:算法

消息隊列做爲一個數據的集散中心,承載了愈來愈多的場景和數據,從最開始的 OLTP 到 OLAP,甚至再到物聯網、人工智能、機器學習等場景,都有很大的想像空間。 在能力上,消息隊列如今擁有了數據,擁有了算力,從承載數據走到理解數據。數據庫

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

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

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

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

在螞蟻金服,消息隊列已經有十多年的歷史了。在0七、08年時,咱們採用了 ESB 這樣的方式來實現消息的機制。架構

那個時候遇到的最頭疼的問題就是丟消息,排查和修復起來很是的痛苦。到了09年,和淘寶共建並上線了新的消息隊列系統,丟消息的問題獲得了有效的改善。框架

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

clipboard.png

極高的可靠性機器學習

舉個例子,經過消息去生成帳單,若是這個消息不可靠,消息丟了,這個時候會發生什麼樣的狀況呢?客戶付了一筆錢,可是在帳單或者消費記錄裏卻看不到這筆記錄,這個時候就很是困惑了。 所以極高的可靠性指的是:消息不能丟。分佈式

極強的一致性

極強的一致性在金融業務當中是很是關鍵和重要的。 假如作一筆轉帳操做,由於種種緣由,好比網絡抖動,轉帳失敗了,若是一致性沒有作好,可能還會收到一條作了一筆轉帳的通知,這個時候系統的數據就不一致了。

持續的可用性

持續的可用性,是指在但願用系統提供的服務能力的時候,這個服務必定是要可用的。 好比說雙十一的時候,線上生成一筆訂單須要支付,必定但願它能很是順利的支付完成。再一個,如今線下的場景很是火,到超市去買東西,結帳的時候也但願掃碼支付要很是順暢,這都是對可用性的要求。

極高的性能

在螞蟻金服,天天有千億級的消息在流轉,峯值的 TPS 也達到了千萬級。在這麼大的體量下,對性能的要求是很是高的。另外,從成本角度和用戶的體驗的角度,性能也是很是須要關注的地方。

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

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

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

ACK 的機制。ACK 機制借鑑了 TCP 裏面的思路,經過發送階段、持久化階段、投遞階段的 ACK 機制,保證了消息在流轉路徑的各個環節上的可靠性。

重試的機制,保證了消息在投遞出去後,當消費端消費不成功的時候,還能夠再次去消費。

經過存儲層的持久化機制和可靠性機制來保證消息數據自己的可靠性。

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

clipboard.png

在第一階段裏面,把發消息和業務本身的業務操做放到本地事務中,發出來的是帶有未提交狀態的消息。 在第二階段,會根據本地事務執行的狀況來決定一階段發出來的消息是提交仍是回滾,若是是回滾,把消息刪掉就行了,若是是提交,會去更新這個消息的狀態,從未提交改爲已提交,接着去作投遞的動做。

若是第二階段中的事務狀態通知丟失了,消息服務端會去主動向消息發送端作事務狀態回查,直到拿到明確的事務提交或者回滾的回查結果。

3. 持續的可用性的實現

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

clipboard.png

可是,因爲受限於單機房部署的架構,當出現機房級別問題的時候,前面的手段就愛莫能助了。

固然,同城雙活架構能夠經過業務流量在兩個機房之間作切換,也能夠經過數據層面的切換等手段來有效的解決機房單點的問題。

clipboard.png

可是,隨着業務增加,同城雙機房模式在容量和容災能力上也逐漸沒法知足業務發展需求了。

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

clipboard.png

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

以轉帳爲例,在異地多活的架構下,收款方跟轉帳人可能在一個邏輯 Zone 裏面,也可能不在一個邏輯 Zone 裏面,甚至他們可能都不在一個城市。這樣帶來一個最重要、最核心的需求就是消息隊列須要具備很是靈活、很是強大的路由能力,能夠作Zone內的路由,能夠作同城跨Zone的路由,也能夠作跨城跨 Zone 的路由。

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

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

有一類會員信息數據,比較有特色:

一、訪問量很是大,把它放到緩存裏面,下降對後端數據庫的壓力。

二、在一次業務請求當中,對這個數據可能有很是屢次的訪問,因此對數據訪問的延遲很是敏感。若是這類數據須要跨城才能訪問到的話,跨城帶來的延時對業務而言是很是難以接受的。所以就要求這類數據從本城市就可以訪問到,每一個城市都須要有全量的這類數據。

三、這類數據對變動的時效性很是敏感。數據變動了,須要很是快的感知到。若是依靠數據庫層面的複製機制來作這件事情,會有大概秒級的延遲。

因而,咱們設計了一個基於消息的方案,來實現一個城市級的緩存更新的機制。重點給 MQ-router 增長了廣播的能力。當這類數據發生變動的時候,以消息的方式發出來,經過 MQ-router 以廣播的形式發送到全部城市去,這樣就達到了多個城市的緩存實時更新的效果。

clipboard.png

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

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

擁抱大數據時代,咱們作了拉模式的消息隊列

有很長一段時間,消息隊列的研發工做都是圍繞着交易、支付、帳務等OLTP的業務展開。因此一直在打磨消息隊列在OLTP場景下的功能。好比,經過數據庫存儲保證消息可靠性,經過推的模式提升消息的實時性等。 隨着業務場景的擴展,特別是大數據時代的到來,愈來愈多的OLAP場景出現了。這個時候前面的這些作法,特別是推的這種模式就遇到不少的困難。

clipboard.png

到了這個階段,咱們去作了基於Log語義的拉模式的消息隊列。 拉模式消息部署在物理機上,經過順序寫本地磁盤的方式去實現拉的語義。在必定時間內比較有效的支持了OLAP這種場景的需求。

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

隨着拉模式的推廣,不少 OLTP 的場景也逐漸的採用了拉模式,提出了不少新的需求。好比 OLTP 對數據可靠性要求比較高,對本地文件存儲可靠性的問題就很是關注。

因爲是基於物理機部署,也遇到不少運維上的難點,好比成本、機型等等的一些問題。特別是物理機機型變化很是多,每次採購可能都不同,很是難以作標準化。在作容量規劃、縮容擴容這些事情時會遇到很是多的困難。

消息是比較重 IO 輕計算的模型,在物理機上就會表現出很是明顯的資源配比不均衡的問題。每每是磁盤已經不夠用了,但 CPU 還很空閒。基於物理機的運維也很複雜,資源利用率不高、容量規劃很差作、擴容縮容困難等問題凸顯。

在作這件事情的時候,咱們一開始採起了一種比較輕量的方式,稱之爲掛盤的模式。 經過掛載的方式,將分佈式文件系統掛在消息隊列應用上面。這個作法的好處是應用系統自己基本上不須要作什麼改造。消息數據透明的寫到了分佈式文件系統上,依靠分佈式文件系統提供的三副本高可靠的能力來保障消息數據的可靠性。

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

因而,咱們開始了計算存儲分離的第二階段:API 模式,在性能上有了一個比較明顯的提高。 這個模式下,消息服務端要作比較大的改動,趁着這個機會,也作了不少功能方面的加強。好比,加入了對全局固定分區的支持,還有發送冪等與強順序的能力等。 同時,把數據落地也作了一個改變,原先數據所有集中在一個commit log中,轉移到了隊列裏面去。這樣帶來的好處是能夠在隊列級別作更細粒度的配置和管控。

這個架構總體而言是一個相對比較完善的計算存儲分離的架構了。在應用層面也作了不少可擴展的設計。

總體上,計算存儲分離的模式給消息隊列打下比較好的基礎,能夠跟螞蟻金服全站的運維模式作很好的適配。

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

消息隊列承載了愈來愈多的消息數據,大量的數據流進來再流出去。都說在大數據時代,數據就是金錢,可是能夠發現這麼多的數據流過消息隊列,卻沒有淘到金。

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

帶着這個問題去看業界的一些發展,獲得了不少新的思路。特別是從Kafka身上獲得了不少的啓發。

因而咱們決定讓計算走進消息隊列,以 streaming 方式爲消息隊列增長了一種計算能力,實現了一個輕量級的非中心式的計算框架,既能夠嵌入客戶端,也能夠嵌入消息的服務端,作一些輕量級的計算,支持一些比較通用和輕量的算子和多種計算窗口語義。

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

clipboard.png

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

總結

經過前面的回顧,咱們能夠看到,消息隊列做爲一個數據的集散中心,承載了愈來愈多的場景和數據。

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

本文做者:兔子醬
閱讀原文本文爲雲棲社區原創內容,未經容許不得轉載。

相關文章
相關標籤/搜索