光大銀行準實時數據平臺架構演進
一、準實時數據平臺
光大銀行數據資產部以提升服務和經營效率為核心目標,負責光大銀行的數據管理和數字化轉型工作,提供關鍵性的底層技術支撐。在整個數字化轉型和業務升級過程中,數據資產部支撐業務關鍵資源、保障關鍵基礎設施運行,在我行扮演著重要角色。
準實時數據平臺則是光大銀行數據資產部-大數據平臺團隊下的重要項目。
準實時數據平臺始于2016年研發,至今已有6-7年的演進,上圖是平臺的整體架構圖,數據流向從左到右。
初期平臺的定位是準實時數據采集與流式計算,向外提供準實時技術支持和按需開發的流式數據加工等服務?;诖耍脚_分為三個模塊:數據采集、數據標準化和數據發布。
簡單來說,我們的數據采集接近于數據貼源層的邏輯,整個流程更像一個實時的數據倉庫。數據源通過兩種方式被傳送到我們的Kafka貼源層:
- 第一種是傳統關系型數據庫的CDC數據,這些數據會通過我們的OGG工具進行同步并存儲于貼源層,另外,業務系統中的有異步導出需求且對延時敏感的數據通過Kafka API直接寫入到貼源層。這些數據大多不可被直接使用于下游業務應用。因此在標準化模塊進行公共邏輯處理,數據會被傳遞到SparkStreaming或Flink實時流式任務,隨后被存儲于Kafka標準層。在標準層進行的處理后,其中的一部分數據可以被直接用于下游應用的消費。
- 另一種數據則通過各種相對復雜的計算邏輯(flink/spark)或批處理技術寫入到我們最終的發布層。與前兩層處理不同,第三層著重處理業務邏輯并將最終的數據提供給下游系統進行實時訂閱。
整個架構經過多年演進,展現出如下三個特點:
- 具有清晰的分層邏輯,并且基于實時數倉的設計邏輯;
- 該架構涵蓋廣泛的組件,包括明顯的業務邏輯處理,初衷是提供流式數據加工架構相關的服務;
- 兼具準時數據的存儲平臺和計算資源服務提供平臺。
隨著大數據領域多年的發展,組件分工也更加細化。組件細分為大數據架構提供更高的可維護性、可擴展性、安全性、穩定性、性能、效率和易用性,使得整個架構更加靈活和強大,能夠更好地滿足不斷增長的數據處理需求。
然而,反觀我們的系統,存在兩個問題:
- 首先,我們必須維護大量業務處理邏輯,隨著時間推移,這對我們平臺的資源分配和能力優化帶來了巨大壓力;
- 其次,我們維護了大量組件,從導入層到存儲層、計算層、上層調度層,使得該平臺的定位相對較模糊,需要更加明確和細化。
因此,我們需要加強對架構的管理,以縮小各個組件之間的差異,同時優化架構的組織和協調,使之更加適應未來的需求。
二、架構演進實踐
針對上述問題,我們結合整個準實時數據平臺的組件架構特點,將平臺拆分成了兩個子平臺:
- 實時數據湖平臺
- 數據服務總線平臺
整個準實時數據平臺維護的相關組件從左到右,包括數據接入和導出層、消息中間件層、數據計算層以及數據存儲層。最上層是調度層,分為資源調度和任務調度,資源調度也由我們完成。
這樣的拆分更好地解決平臺定位不清晰的問題,同時也提高了平臺組件之間的協作效率。
數據服務總線平臺拆分后以Kafka為中心的部分,該部分包括前端封裝的SDK和OGG,以及隨后引入的Schema Registry組件,致力于提供更完備的流式數據供給能力。
同時,我們引入了Apache Hudi,并結合原有的流式計算組件生態,構建出實時數據湖平臺,旨在實現實時數據的高效處理和存儲。該平臺致力于實時貼源數據存儲,在數據的管理、查詢和可視化分析等方面提供優化的解決方案。
1、實時數據湖
下圖是實時數據湖的數據處理鏈路,中間是綠色的部分是數據湖的存儲層,由Hudi和HDFS實現。
左邊是數據導入層,分為兩部分:
- 一是我們存量的貼源數據,基于Spark的批量任務從數據湖導入;
- 二是實時貼源數據,基于Flink實時流任務,從數據服務總線貼源層導入。
這兩部分共同匯總在實時數據湖,實現了一個完整的實時貼源數據存儲,對外提供分鐘級的一個貼源的數據的可見性。
右邊是數據導出層,分三種場景:
- 一是基于 Spark/Hive的這種批處理的導出的能力,給下游的數倉和其他業務系統提供更穩定、低時延的數據可用性;
- 二是基于Flink去提供秒級的實時數據的消費的能力;
- 三是基于內部的多源分析查詢平臺(Presto),提供實時數據的OLAP查詢能力。
實時數據湖提供的是分鐘級貼源數據存儲,填補了數據湖天級延遲場景和數據服務總線秒級延遲場景之間的空白。實時數據湖不僅是一種存儲方式,更提供了快速響應業務需求能力,實現了現代化的數據處理,推動了企業數字化轉型進程。
此外,對于光大內部許多業務而言,對數據的實時性并不需要完全做到秒級,分鐘級的延遲就已能夠滿足當前六成的業務需求。
下圖是我們內部一個核心的業務運營系統的數據處理鏈路,在引入實時數據湖之前和之后的演進路線:
未使用實時數據湖之前,數據來源于Kafka的ods層,通過Spark Streaming的流處理寫入Hbase,然后經過Hive的Tez批處理,最終通過基于Hive on Hbase表提供給業務查詢。整條數據鏈路的延遲時間非常長,達到了小時級別,這種延時對運營系統的性能影響非常大,明顯減緩了業務觸達的時效性。
演進后是基于Hudi的改進的數據處理鏈路,可以達到分鐘級的一個延遲。數據來源還是Kafka貼源層,會基于Flink的流處理,再去實時導入到Hudi,最終通過 Presto提供給業務實時貼源數據的交互查詢的能力。
整條鏈路經過改造后,數據可見性延遲從小時級別下降到了分鐘級別,處理環節相對簡化,同時Hudi提供了更穩定的數據來源。
2、數據服務總線
數據服務總線方面的實踐,主要涉及三個方面:
- 基于Confluent開源的Schema Registry實現了schema解耦;
- 對Kafka的原生API進行了封裝,以便更好地對外提供服務;
- 提升了服務的可觀測性和可視化水平。
1)Schema的解耦
下圖是優化前的數據流轉圖。
黑色實線表示數據流轉的方向,黑色虛線表示元數據流轉的方向。數據來源于Oracle數據庫,通過OGG進行導入,以Avro的格式,通過Kafka做數據層的解耦,由下游基于Schema去做解析,下游解析數據的Schema來源于上游OGG接收到數據變更自動生成(即圖中藍色的.avsc文件)。
所以,在上游表結構發生變更時,游必須同步去更新這個Schema文件才能完成數據的解析,這個Schema文件導致上下游系統在數據層是未完全解耦的狀態;當上游系統發生變更時,下游系統需要先基于舊的Schema完成舊數據的消費,然后再把新的Schema同步過來,重啟服務使用新的Schema消費新的數據。
總的來說,這個變更流程比較復雜,且下游對上游存在依賴,并且如果上游在投產的時候,沒有來得及通知下游,當Schema變更以后,下游系統會使用舊的Schema去解析新的數據,可能就會導致無法預知的程序宕機,影響下游服務的穩定運行。
為解決這一問題,我們引入了Confluent的Schema Registry來實現Schema的解耦。
上圖展示了在引入了Schema Registry后的數據流轉圖。
數據的流向和之前一樣,主要區別是:在OGG側感知到源端的表結構變更時,會主動去Schema Registry注冊新的Schema,同時將獲取到的Schema ID和數據一起寫入Kafka。下游消費系統從消息中獲取新的Schema ID,也會去Schema Registry請求獲取對應的Schema,并使用這個Schema去解析數據。
因此,當Schema發生變化時,下游的自動獲取和更新,免去了非必要的重啟和未通知變更情況下的宕機問題。同時,我們通過Schema Registry將Schema中心化存儲起來,方便后續進一步的管理。同時,引入Schema Registry以后,上游系統和下游系統都會對它有很強的依賴關系,這對Schema Registry服務本身的高可用提出了高要求。
①Schema Registry高可用實踐
上圖右側是Schema Registry單個實例的內部實現原理。最上層是接口層,對外提供Restful形式的訪問接口,注冊請求(寫請求)過來后,會基于內部的store層將數據以消息的形式寫入Kafka的topic中,也就是說Schema Registry底層的真實存儲實際上是一個Kafka的topic;而Store層會緩存所有的Schema,對于讀請求,會直接從內存中獲取。
高可用實踐分為客戶端和服務端兩部分:
客戶端:高可用的一部分依賴于客戶端本身對Schema的緩存,在這種情況下,服務端如果暫時不可用,只會影響新增Schema的注冊和解析;同時為了讓服務端部署多個實例,以此避免單點問題導致的服務不可用問題,也要求客戶端配置多實例地址。因此,我們在自研的SDK里集成了自動化配置這個功能。
服務端:除多實例部署以外,每個實例本身也做了獨立的部署,以此避免和其他服務混部造成影響;第二層是服務層自身的存儲緩存,在底層存儲出現問題時,可以提供讀服務。
同時,針對業務的需求,我們實現了集群跨域部署和容災方案。
在我們內部,存在跨域獲取數據的需求,自然就會產生跨域獲取Schema的需求。
上圖有兩個域,左邊是DC A,右邊是DC B。在A域里,生產者將相關數據寫入Kafka集群,將Schema注冊到Schema Registry服務。在消費端,同時在A域和B域都會有對數據的消費需求,數據的同步一般的方案就是Replicator或MM等工具完成,比如topic1同步到B域對應A.topic1;在B域,拿到數據后,需要獲取Schema ID對應的Schema才能去解析出數據。因此,我們需要跨域獲取Schema的解決方案。
上圖最下面藍框中的就是一個跨域的Schema Registry集群的實現。橙色是A域的Schema Registry實例,綠色是B域。整個集群會有一個主節點,通過參數設置只能在A域產生。同時,Schema Registry底層的存儲也使用A域的topic(即圖中的_schemas),這是為了保證數據沒有跨域寫入,并盡量避免因為網絡問題導致的數據重復或丟失問題。
對于寫請求,都會轉發給主節點實現,這要求B域中的Schema Registry實例開通和A域中的Schema Registry實例之間的網絡關系;對于讀請求,節點要緩存Schema數據,需要和底層的存儲通信,這要求B域中的Schema Registry實例開通和A域中的Kafka Broker節點之間的網絡關系,讀請求是增量獲取,跨域請求對網絡流量的影響也會比較小。
針對單個域的Kafka集群故障或機房故障,數據本身的備份可以通過同步工具完成,由于Schema Registry底層的存儲也是一個topic,它的數據也可以通過這種方式備份。在主節點集群出現問題時,我們可以通過腳本去實現參數的一鍵切換,從而保證服務的可用性。
以上是整個Schema Registry的跨域災備方案。
我們使用的Schema Registry是Confluent的開源版本,在光大銀行的系統整合過程中,進行了一些改造,主要包括兩個方面:
- 安全&權限:這是將開源系統集成到企業內部所必需的改進之一,所以Schema Registry的實現充分考慮到這點,為使用者提供了標準的插件接口。我們基于這個接口實現了一個RBAC鑒權機制,確保服務的安全性,同時還增加了審計日志,以便進行用戶請求的跟蹤。
- 運維:我們先將服務與Kerberos整合,再把服務的內部指標和行內監控系統進行了打通。上圖是測試環境的示例,由于Schema Registry服務本身對高可用性要求較高,我們在監控和報警方面前期做了很多工作,未來也將不斷優化。
2)SDK封裝
我們對Kafka客戶端所做的二次開發做了SDK封裝,提供統一的客戶端接口,解決了以下問題:
- 減少不同客戶端版本帶來的性能差異和穩定性問題;
- 方便升級管理、災備切換等;
- 更好地規范客戶端行為,增強對客戶端的數據面控制。
在上圖右側,我們展示了SDK已經實現及計劃實現的特性,下面重點介紹下消費定制化這一特性。
如圖所示,在消費定制化的使用場景中,某個生產者寫入的某個數據,在下游可能并不是關心的,以訂單數據為例,有些業務可能只關心訂單的流轉狀態,有些業務只關心下單后的物流信息。因此,在大部分情況下,下游消費數據只是上游寫入數據的一個子集,不同的消費者子集也可能不同。
基于這些場景,我們實現了消費定制化訂閱的特性,將業務真正關心的schema托管到我們自研的Schema Manager服務中,在SDK消費時,可以提供給下游業務真正關心的數據,從而滿足不同消費者的不同數據需求。
該特性的對外暴露由SDK封裝實現,底層依賴于Schema Registry和Schema Manager,其中Schema Registry實現了用于中心化托管和對外服務的schema寫入,而Schema Manager實現了用戶自定義schema的中心化托管和對外服務,在SDK側,我們實現了和這兩個服務之間的交互,及自定義schema的獲取,并完成底層異常情況的處理以及消費數據的抽取。
上圖展示了消費定制化特性的處理流程,其核心實現有兩個方面:
一是實現了和Schema Manager之間交互及容錯的能力,并且提供給客戶端調整能力,實現了一層緩存以提高效率。在未來,我們將考慮在客戶端中實現checkpoint機制,以提高可用性。
二是實現了基于讀schema解析時的兼容性,對于一些字段的偏差,我們可以自動處理,并提供給業務一些常用匹配策略的配置。
3)可觀測性&可視化
最后介紹一些我們在觀測性和可視化方面做的事情。
首先,我們對Kafka進行了全面的監控。之前,我們發現基于Kafka的機制的產品端監控粒度比較低,且缺失很多關鍵指標,如Kafka服務端網絡請求處理線程的繁忙率,業務側消費延遲等。因此,我們結合Kafka本身的指標以及我們內部的云原生監控體系,實現了更細粒度的監控報警方案,以更好地掌握Kafka的狀態。
其次,我們還開發了服務控制臺。前面我們提到,通過Schema Registry我們可以將schema的中心化存儲。但是,這種數據并不是一種結構化的存儲,這就需要我們通過控制臺進行可視化的管理。自定義的schema也通過控制臺去完成創建、更新和刪除的操作。下面的圖展示了一個租戶自定義schema列表的示例。
三、總結&未來規劃
1、總結
通過結合大數據領域新興技術,我們對整個平臺進行了拆分,解決了多項問題,當前準實時數據平臺實現了以下收益:
1)更清晰的平臺邊界;
2)覆蓋分鐘級實時貼源數據場景;
3)數據服務總線生態建設;
4)提升了運維和運營能力。
2、未來規劃
1)實時數據湖
實時數據湖平臺目前處于持續落地階段,未來我們將持續遷移適用于分鐘級實時數據庫的全部貼源場景,同時探索基于行業經驗的湖倉一體和流批一體場景。
2)數據服務總線
- 持續圍繞消息中間件生態進行拓展,基于SDK實現客戶端的災備切換功能,并結合服務端的災備,共同實現平臺級別的災備方案;
- 由于總線的上下游接口的一個重要計算框架是Flink Connector,因此我們將基于它進行二次開發,實現部分核心功能,為接入的業務提供統一的體驗;
- 除增強客戶端接入能力外,我們將積極開發管理控制臺,將一些重要的Kafka運維操作和服務部分運營能力整合到我們的控制臺上,以提高整體的運維和運營效率;
- 著手計劃長期的信創集群建設。
講師介紹
張旭,光大銀行準實時數據平臺技術負責人,專注于分布式系統內核研發。在OLAP & 消息中間件領域有較豐富經驗。開源愛好者,Apache RocketMQ committer,Prometheus contributor。