網上有很多關于pos機改造,使用CDC模式改造遺留系統的知識,也有很多人為大家解答關于pos機改造的問題,今天pos機之家(www.shbwcl.net)為大家整理了關于這方面的知識,讓我們一起來看下吧!
本文目錄一覽:
1、pos機改造
pos機改造
項目改造背景及挑戰在我們經歷的各種遺留系統改造之旅中,使用絞殺者模式來改造一個巨大的單體服務,是一種被廣泛采用且驗證行之有效的手段,在應用傳統的絞殺者模式時,通常采用逐步替換的方式,將遺留系統中某一獨立的部分抽取出來進行改造,最后通過反向代理等方式,將流量倒入到新的服務中。
但是在我們的案例中,被改造的領域服務是客戶的核心業務,客戶強烈希望在整個改造過程中,不要對現有正在運行的系統造成影響,所以僅僅采用絞殺者模式是不夠的,我們還需要采用新老并行模式來完成整個遷移改造。
當使用并行運行時,我們不是調用新舊實現的其中之一,而是同時調用二者,以允許我們比較其結果以確保它們是等效的。盡管調用了兩種實現,但在任何給定的時間內,只有一個實現的結果是正確的。一般而言,在不斷校驗并相信我們的新實現之前,我們認為舊實現的結果是正確的。
「《Monolith To Microservices》」
通過新老并行模式,原有的系統不會受到影響,可以繼續提供服務,待新的服務完成遷移并通過驗證之后,再將流量遷移到新的系統。采用新老并行模式可以以增量的模式進行遷移改造,并且在出現問題的時候能夠輕松回滾,確保核心業務的安全。具體介紹可以參考zalando 的工程實踐。
在新老并行模式運行過程中,為了達到使新服務能夠完全平行替代舊服務,需要將舊服務里新產生的變化,及時同步到新服務里來(對于遺留數據只需要一次性的遷移即可)。在各種因素以及客戶業務需求的影響下,我們選擇了 Event Sourcing 作為基本架構來構建我們新領域服務。Event Sourcing 是一種通過記錄一系列的領域事件來完成對系統狀態的持久化,對于 Event Sourcing 更加詳細的介紹可以參看之前的這篇《如何正確使用Event Sourcing》。
鑒于新服務中持久化的都是一系列的領域事件,所以很難將遺留系統中產生的變化直接持久化到新服務中,最好的方式是通過調用新服務提供的 API,由新服務通過 Command 產生 Event,然后再存儲到 Event Store 中,完成持久化。
同時遺留單體系統中的代碼倉庫已經非常龐大,并且復雜到難以修改,任何對于遺留系統的代碼修改都需要經過繁復的測試和嚴格的 Code Review,同時也會增加交付開發人員的認知負擔,并且還會給現有系統帶來一定的風險。
基于以上背景,我們發現,通過修改遺留系統代碼的方式來完成新老兩個系統之間數據的同步代價是比較大的,而且會引入一定的風險。
以上種種限制使得我們選擇了CDC(Change data capture)模式來完成我們對遺留系統數據的捕捉與遷移。
使用 CDC 模式來完成新老數據同步什么是 CDC 模式和 DebeziumCDC 模式是一種對變化的數據進行監控并捕獲,以便其他服務也能夠響應這些變化的模式。對于監控數據庫的變化而言,Debezium 是 CDC 模式的一個非常成熟的實現。當使用 Debezium 來連接 MySQL 時,Debezium 會讀取 MySQL 的 binary log (binlog) 獲取到數據庫產生的變化。同時,Debezium 還是一個 Kafka connect,通過配置,能夠將數據庫產生的變化推送到特定的 Kakfa Topic 中。
通過 Debezium,我們便可以捕獲到所有遺留系統數據庫產生的變化,并將其推送到 Kafaka 特定的 Topic 中去,只要新服務能夠響應這些變化,就可以將舊系統中數據產生的變化同步到新系統里去。
但目前而言,新服務是無法直接響應這些遺留系統數據庫的變化的,原因是新服務接受的是有業務含義的 Command,而不僅僅是一些數據庫的變化。但根本原因在于,我們捕獲到的數據庫變化只是數據庫行級別的變化,缺失了特定的業務含義,所以我們也無法直接利用這些數據與我們的新服務連接起來。
將這些捕獲到的數據庫變化賦予業務含義,并將其轉換為特定的 Command,這是我們面臨的下一個挑戰。
從 CDC 到 Command要完成這個挑戰,就需要深入細節了。為了方便說明,我在這里準備了一個非常簡單的例子。
還是以我們非常熟悉的電商領域商品項為例,假設一個 Product 聚合根,管理著多個 Photo 聚合,它們之間的關系在遺留系統數據庫中用 ERD 表示如下:
經過前期的事件風暴工作坊,我們可以得到一系列關于 Product 聚合根的領域事件:
Product 已增加Product 的 Photo 已增加…由于我們的新服務采用了 Event Sourcing 架構,并且系統內的 Event 設計嚴格遵循事件風暴工作坊產出的領域事件,在新服務中,接受的是像在 Product A 下增加 Photo這樣的 Comand。
有了例子之后, 我們可以將之前描述的問題更加具體一點:當收到一條消息表明 Photo 表中的數據發生了變化,應將其識別并轉變為在 Product A 下增加 Photo或更改 Photo A 為封面圖片這樣的 Command。
接下來讓我們仔細分析一下 Debezium 所捕獲到的變化數據的結構,繼續上面的例子,如下是一個典型的 Debezium 產生的 Kafka 消息的 payload 結構:
{ "before": null, "after": { "id": "61CFF6E6-A7AA-43BB-8D6D-A8676CFF59AE", "productId": "E78E3F5A-2275-4C2D-AA6E-1F0282E6CC08", "filePath": "48F3AE46-D6A5-4F14-8FE3-7B82B7EB6537", "order": 0, "isCover": true, } "source": {...some source meta infORMation}, "op": "c", "ts_ms": 1631690854515, "transaction": { "Id": "file=mysql-bin-changelog.000010,pos=40908353", "total_order": 1, "data_collection_order": 1 }}
從這個消息的結構和內容可以看出,該消息里面不僅完整的展示了數據庫里某項記錄在變化前后的所有信息,同時還有一些附加的元信息。在這些元信息中,有兩項數據最值得我們去注意。
一個是op,根據Debezium 的官方文檔,這個字段表明了這次變化的變化類型,這個字段可能的值有:
C: 表示創建U: 表示更新D: 表示刪除R: 表示讀取(如果是一個 Snapshot 的話)通過這個字段,我們可以快速且準確的推斷出當收到某條變化的消息時,遺留系統數據庫的某項數據發生了怎樣的變化。比如上面這個例子,我們可以推斷出來,有一張新的圖片被添加到某個 Product 上面。
但是到目前為止,可以將這樣的消息轉換為在Product A下增加Photo這樣的 Command 嗎?
很遺憾還不能,因為根據 Debezium 的實現以及我們的配置,每張表的更新都會被發送到不同的 Kafka Topic 中去,當收到圖片被添加的消息時,還有可能是添加了一個 Product 的同時添加了這個 Product 的 Photo,所以這個行為不應該被識別為添加圖片的 Command,而應該被識別為創建一個 Product的 Commnd。
為了能夠準確地將數據庫中發生的變化識別為 Commnd,我們需要收集并分析更多的數據,這就需要利用消息體里的另外一個字段——transaction。
Transaction 字段描述了捕獲到的這一次變化里關于 Transaction 的一些信息,這些信息包括了這次變化的“transactionId”,以及這個變化在這次 transaction 里的順序。
同時,Debezium 捕獲到的不僅僅是某個表中的某項記錄發生變化,同時它還會捕獲到每次數據庫關于 Transaction 的一些原始信息,消息格式如下:
{ "status": "END", "id": "file=mysql-bin-changelog.000010,pos=40908353", "event_count": 2, "data_collections": [ { "data_collection": "product-service@photo", "event_count": 1 }, { "data_collection": "product-service@product", "event_count": 1 } ]}
在每一次數據庫的 transaction 開始或者結束的時候,我們都能通過 debezium 收到這樣一條消息,這個消息里面,我們可以得知某一個 Transaction 的狀態,id,這次 Transaction 里面有哪些表發生了變化,以及變化的數量是多少。
在這些數據中,我們最為關注的就是 Transaction 的id,可以發現在前述關于數據表變化的消息體里面也存在這個字段,通過這個字段,我們可以將某一個 Transaction 下所有產生的變化都聚合到一起,根據聚合之后的數據再來判斷應該將其識別轉換為哪種 Command。比如說,要是這個變化的聚合里面有一個 Product 被新增了,那么我們就可以確定的是這肯定是一個新增Product的 Command,即便這個變化的聚合里面顯示出有 Photo 被新增,那也不應該被識別為成添加圖片的 Command。
其實作出上面的推論還是有一個隱含前提,就是遺留系統的一些行為和操作,都是在一個 Transaction 中,如果同一個操作不在同一個 Transaction ,那么我們的推論也就無法成立。好在在我們的真實案例中,客戶采用了成熟的 ORM 框架(Prisma),每一個有業務含義的行為所造成的修改都在同一個 Transaction 中并保存到數據庫。在開發過程中,也需要在遺留系統的前端不斷操作驗證并加以單元測試才能確保我們能夠準確地識別出所對應的 Command。
至此,我們所有要解決的問題都能夠得到解決了,我們已經能夠將遺留系統數據庫與新系統的數據庫之間的 gap 填平了,兩者之間的通道也能夠建立了。我們終于勝利了!
基于此種解決方案,我們將整個遺留系統改造分為了三個階段,
階段一:前端對遺留系統讀和寫,但是對遺留系統所造成的修改都會被同步到新系統中階段二:前端對遺留系統進行寫操作,但是對于讀操作都會被引向新系統階段三:待對新系統做好完整的驗證后,新系統就會被作為唯一可信的數據源進行讀寫了更多的細節常言道,魔鬼都在細節里,不過鑒于篇幅有限,已經無法再用文字展開更多了,只能通過時序圖來介紹 CDC Procrssor 服務里更多的細節,包括如何通過Transaction來聚合 Debezium 消息以及整個消息處理流程。
總結最后總結一下,因為被改造的業務是客戶的核心業務,基于不影響原有業務的考慮下選擇了新老并行模式來完成整個遺留系統改造。我們選擇了 CDC 模式(Debezium)來將遺留系統中產生的變化同步到新服務中。在同步過程中,由數據層的變化推導出業務意圖是成功的關鍵。在其他運用絞殺模式的改造中,如果能夠在更上層的地方做分支也是一種好的思路(參考 Decorating Collaborator Pattern),這樣可以更好地還原業務。最后,在使用 CDC 模式來完成遺留系統改造時,數據完整性和性能都是關鍵指標,在不丟失數據的情況下應越快越好。
文/ Thoughtworks 張雙海
更多精彩洞見,請關注公眾號Thoughtworks洞見
以上就是關于pos機改造,使用CDC模式改造遺留系統的知識,后面我們會繼續為大家整理關于pos機改造的知識,希望能夠幫助到大家!
