微服務之數據同步Porter

Porter是一款數據同步中間件,主要用於解決同構/異構數據庫之間的表級別數據同步問題。

背景

在微服務架構模式下深刻的影響了應用和數據庫之間的關係,不像傳統多個服務共享一個數據庫,微服務架構下每個服務都要有自己的數據庫。如果你想獲得微服務帶來的好處,每個服務獨有一個數據庫是必須的,因爲微服務強調的就是鬆耦合。我們希望數據庫就和服務一樣,要有充分的獨立性、可以和服務一起部署、一起擴展、一起重構。同時,還需要兼顧數據中心的數據聚合、DBA的多種數據庫備份、報表中心的業務報表等等矛盾問題。因此便產生了「Porter」項目。

微服務改造過程中,無法避免的一個坎,那就是垂直拆庫,根據不同的子服務,把過去的「一庫多服」拆分成「一庫一服」。

一庫多服還是一庫一服?

不管是否是微服務架構,應用的各個模塊之間都需要頻繁的通信、協作、共享數據,實現系統的整體價值。區別點在於單體應用是通過本地方法調用來完成;在微服務中是通過遠程API調用完成。
而共享數據最賤的方式就是採用共享數據庫模式,也就是單體應用中最常用的方式,一般只有一個數據庫,如圖一庫多服和一庫一服的方式:

一庫多服的架構模式通常會被認爲是微服務架構下的反範式,它的問題在於:

穩定性:單點故障,一個數據庫掛掉,整批服務全部停止。服務獨立性被扼殺?

耦合性:數據在一起,會給貪圖方便的開發或者DBA工程師編寫很多數據間高度依賴的程序或者工具;

擴展性:無法針對某一個服務進行精準優化或擴展,服務會大體分爲兩個讀多寫少、寫多讀少,數據庫優化是根據服務而來的,不是一篇而論。

所以隨行付內部一般推薦的做法:是爲每一個微服務準備一個單獨的數據庫,即一庫一服模式。這種模式更加適合微服務架構,它滿足每一個服務是獨立開發、獨立部署、獨立擴展的特性。當需要對一個服務進行升級或者數據架構改動的時候,無須影響到其他的服務。需要對某個服務進行擴展的時候,也可以手術式的對某一個服務進行局部擴容。

那麼問題來了,在改造中我們發現,以下問題,誕生了該項目:

報表中心和前端詳細頁都存在SQL Join方式,經歷我們一庫一服的拆分後,無法在繼續使用SQL Join方式了…
數據中心,做得是數據聚合,數據拆分後,給數據中心帶來了很大的麻煩…
微服務之後,各個應用模塊對數據庫的要求出現了分歧,數據庫類型多元化自主選擇還是統一…
等等…

Porter介紹

Porter是一個集中式的數據處理通道,所有的數據都在這個數據處理平臺匯聚、分發。Porter是一個無中心、插件友好型分佈式數據同步中間件。默認註冊中心插件實現爲zookeeper, 當然,你也可以基於註冊中心接口實現自定義註冊中心模塊。在Porter的主流程外分佈着集羣插件、源端消費插件、源端消息轉換器插件、目標端寫入插件、告警插件、自定義數據定義插件等插件模塊,除了集羣插件、告警插件是Porter任務節點全局作用域外,其餘插件模塊都隨着同步任務的不同而相應組合。得益於良好的設計模式,Porter才能爲大家呈現如此靈活的擴展性與易用性。

功能

Porter始於2017年,提供數據同步功能,但並不僅僅侷限於數據同步,在隨行付內部廣泛使用。主要提供一下功能:

原生支持Oracle|Mysql到Jdbc關係型數據庫最終一致同步
插件友好化,支持自定義源端消費插件、目標端載入插件、告警插件等插件二次開發。
支持自定義源端、目標端表、字段映射
支持節點基於配置文件的同步任務配置。
支持管理後臺同步任務推送,節點、任務管理。提供任務運行指標監控,節點運行日誌、任務異常告警。
支持節點資源限流、分配。
基於Zookeeper集羣插件的分佈式架構。支持自定義集羣插件。

架構設計

Porter節點通過註冊中心實現分佈式集羣,並根據資源需求動態擴縮容。Portert與註冊中心協商了一套任務、節點、統計接口,Porter節點通過監聽註冊中心接口數據的變化實現任務的分配管理。配置管理後臺遵守並實現註冊中心的接口規範,實現對Porter節點遠程管理。註冊中心同樣有一套分佈式鎖機制,用於任務資源的分配。
在這個機制外,Porter節點可以通過本地配置文件的方式實現任務的定義。

原理介紹:

1、基於Canal開源產品,獲取MySql數據庫增量日誌數據。
2、管理系統架構。管理節點(web manager)管理工作節點任務編排、數據工作節點(TaskWork)彙報工作進度
3、基於Zookeeper集羣插件的分佈式架構。支持自定義集羣插件
4、基於Kafka消息組件,每張表對應一個Topic,數據節點分Topic消費工作

處理流程

爲了保證數據的一致性,源端數據提取與目標端插入採用單線程順序執行,中間階段通過多線程執行提高數據處理速度。對照上圖就是SelectJob與LoadJob單線程執行,ExtractJob、TransformJob線程並行執行,然後在LoadJob階段對數據包進行排序,順序寫入目標端。

正如文章開頭所說,告警插件與註冊中心插件在多個任務間共享,每個任務根據源端與目標端的類型、源端數據格式選擇與之相匹配的處理插件。也就是說告警插件、註冊中心插件與Porter節點配置相關,數據消費插件、目標端插件、自定義數據處理插件等插件與任務配置相關。

插件化設計

Porter通過SPI規範結合單例、工廠、監聽者模式等設計模式,實現了極大的靈活性與鬆耦合,滿足不同場景的二次開發。具體涵蓋如下四個方面的插件化設計:
註冊中心插件
源端消費插件
目標端載入插件
自定義數據處理插件





集羣機制

Porter的集羣模式依賴集羣插件,默認的集羣插件基於zookeeper實現。Porter任務節點和管理節點並不是強制綁定關係,任務部署可以通過任務配置文件,也可以通過管理節點推送。管理節點還可以管理節點、收集、展示監控指標信息等,是一個不錯的、簡化運維的管理平臺。同樣的,可以基於zookeeper數據結構協議實現你自己的管理平臺。集羣模式下的系統結構:

zookeeper集羣模式插件

zookeeper數據結構協議:

Porter的集羣機制主要有以下功能:

實現節點任務的負載,當前任務節點失效後自動漂移到其他任務節點
實現任務節點與管理節點的通信
實現任務處理進度的存儲與拉取
實現統計指標數據的上傳(最新的開發版本支持自定義統計指標上傳客戶端,原生支持kafka)
用於節點、任務搶佔的分佈式鎖實現
基於文件系統的單機模式插件

最新開發版支持Porter任務節點以單機模式運行,不依賴管理後臺和zookeeper,通過配置文件配置任務。單機模式是一種特殊的集羣模式,僅支持部分集羣功能,但簡化了任務部署的複雜性,靈活多變。

實現任務處理進度的存儲與拉取
實現統計指標數據的上傳
Porter任務節點運行模式的配置方式

#zookeeper集羣配置
porter.cluster.strategy=ZOOKEEPER
porter.cluster.client.url=127.0.0.1:2181
porter.cluster.client.sessionTimeout=100000

#單機模式配置
porter.cluster.strategy=STANDALONE
porter.cluster.client.home=/path/.porter

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章