微服務之間的數據依賴問題,該如何解決?

微服務,顧名思義,就是將我們程序拆分爲最小化單元來提供服務。在一體化系統中,各個微服務也是不可能獨立存在的,那麼微服務之間涉及到的數據依賴問題,應該怎麼處理呢?我們從場景入手來分析考慮此類問題。

一、場景

在一個供應鏈系統中,存在商品、銷售訂單、採購三個微服務,他們的主數據部分數據結構如下:

商品:

訂單和子訂單:

採購單和子訂單:

在設計這個供應鏈系統時,我們需要滿足以下兩個需求:

初期我們的方案是這樣設計的:嚴格按照的微服務劃分原則將商品相關的職責存放在商品系統中。因此,在查詢訂單與採購單時,如果查詢字段包含商品字段,我們需要按照如下順序進行查詢:

爲了方便理解這個過程,訂單查詢流程圖如下圖所示:

初期方案設計完後,很快我們就遇到了一系列問題:

結果就是業務方每次查詢訂單或採購單時,只要帶上了商品這個關鍵字,查詢效率就會很慢而且老是失敗。於是,我們重新想了一個新方案——數據冗餘,下面我們一起來看下。

二、數據冗餘的方案

數據冗餘說白了就是在訂單、採購單中保存一些商品字段信息。

爲了方便理解,我們藉助上面實際業務場景具體說明下,看看兩者的區別。

商品:

訂單和子訂單:

採購單和子訂單:

調整架構方案後,每次查詢時,我們就可以不再依賴商品服務了。

但是,如果商品進行了更新,我們如何同步冗餘的數據呢?在此分享 2 種解決辦法。

看到這裏是不是覺得很眼熟了呢?沒錯,這就是我們上一篇提到過的數據一致性問題。那麼這 2 種方案會出現哪些問題呢?

如果商品服務每次更新商品都要調用訂單與採購服務,然後再更新冗餘數據,則會出現以下兩種問題。

因此,第一個解決辦法直接被我們否決了,即我們採取的第二個解決辦法——通過消息發佈訂閱的方案,因爲它存在如下 2 點優勢。

此時,我們的架構方案如下圖所示:

這個方案看起來已經挺完美了,而且市面上基本也是這麼做的,不過該方案存在如下幾個問題。

  1. 在這個方案中,僅僅保存冗餘數據還遠遠不夠,我們還需要將商品分類與生產批號的清單進行關聯查詢。也就是說,每個服務不只是訂閱商品變更這一種消息,還需要訂閱商品分類、商品生產批號變更等消息。下面請注意查看訂單表結構的加粗部分內容。

以上只是列舉了一部分的結構,事實上,商品表中還有很多字段存在冗餘,比如保修類型、包換類型等。爲了更新這些冗餘數據,採購服務與訂單服務往往需要訂閱近十種消息,因此,我們基本上需要把商品的一小半邏輯複製過來。

  1. 每個依賴的服務需要重複實現冗餘數據更新同步的邏輯。前面我們講了採購、訂單及其他服務都需要依賴商品數據,因此每個服務需要將冗餘數據的訂閱、更新邏輯做一遍,最終重複的代碼就會很多。

3.MQ 消息類型太多了:聯調時最麻煩的是 MQ 之間的聯動,如果是接口聯調還好說,因爲調用哪個服務器的接口相對可控而且比較好追溯;如果是消息聯調就比較麻煩,因爲我們常常不知道某條消息被哪臺服務節點消費了,爲了讓特定的服務器消費特定的消息,我們就需要臨時改動雙方的代碼。不過聯調完成後,我們經常忘了改回原代碼。

爲此,我們不希望針對冗餘數據這種非核心需求出現如此多的問題,最終決定使用一個特別的同步冗餘數據方案,接下來我們進一步說明。

三、解耦業務邏輯的數據同步方案

解耦業務邏輯的數據同步方案的設計思路是這樣的:

此時,整個方案的架構如下圖所示:

以上方案就能輕鬆解決如下兩個問題:

不過,該方案的 “缺點” 是增加了訂單、採購等數據庫的存儲空間(因爲增加了商品相關表)。

仔細計算後,我們發現之前數據冗餘的方案中每個訂單都需要保存一份商品的冗餘數據,假設訂單總數是 N,商品總數是 M,而 N 一般遠遠大於 M。因此,在之前數據冗餘的方案中,N 條訂單就會產生 N 條商品的冗餘數據。相比之下,解耦業務邏輯的數據同步方案更省空間,因爲只增加了 M 條商品的數據。

此時問題又來了,如何實時同步相關表的數據呢?我們直接找一個現成的開源中間件就可以了,不過它需要滿足支持實時同步、支持增量同步、不用寫業務邏輯、支持 MySQL 之間同步、活躍度高這五點要求。

根據這五點要求,我們在市面上找了一圈,發現了 Canal、Debezium、DataX、Databus、Flinkx、Bifrost 這幾款開源中間件,它們之間的區別如下表所示:

從對比表中來看,比較貼近我們需求的開源中間件是 Bifrost,原因如下:

因此,最終我們使用了 Bifrost 開源中間件,此時整個方案的架構如下圖所示:

四、上線效果

整個架構方案上線後,商品數據的同步還算比較穩定,此時商品服務的開發人員只需要關注自身邏輯,無須再關注使用數據的人。如果需要關聯使用商品數據的訂單,採購服務的開發人員也無須關注商品數據的同步問題,只需要在查詢時加上關聯語句即可,實現了雙贏。

然而,唯一讓我們擔心的是 Bifrost 不支持集羣,沒法保障高可用性。不過,到目前爲止,它還沒有出現宕機的情況,反而是那些部署多臺節點負載均衡的後臺服務常常會出現宕機。

最終,我們總算解決了服務之間數據依賴的問題。

五、總結

這裏我們探討了服務間的數據依賴問題,並給出了目前較爲合適的解決方案。其實這裏提到的方案不是一個很大衆的方案,肯定會存在一些遺漏的問題沒考慮,如果你有更好的方案,歡迎留言討論。

作者:我愛娃哈哈

來源:blog.csdn.net/u010223407/article/details/121245298

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/UmRyfCwPt6MyG43OWZJt5w