1. 微服務(wù)之間的數(shù)據(jù)依賴問題,該如何解決?

        共 7038字,需瀏覽 15分鐘

         ·

        2024-08-19 10:30

        來源:網(wǎng)絡(luò)

        ?? 歡迎加入小哈的星球,你將獲得: 專屬的項(xiàng)目實(shí)戰(zhàn) / 1v1 提問 / Java 學(xué)習(xí)路線 / 學(xué)習(xí)打卡 / 每月贈(zèng)書 / 社群討論

        • 新項(xiàng)目:《從零手?jǐn)]:仿小紅書(微服務(wù)架構(gòu))》 正在持續(xù)爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17..., 點(diǎn)擊查看項(xiàng)目介紹;
        • 《從零手?jǐn)]:前后端分離博客項(xiàng)目(全棧開發(fā))》 2期已完結(jié),演示鏈接:http://116.62.199.48/;

        截止目前,累計(jì)輸出 54w+ 字,講解圖 2330+ 張,還在持續(xù)爆肝中.. 后續(xù)還會(huì)上新更多項(xiàng)目,目標(biāo)是將 Java 領(lǐng)域典型的項(xiàng)目都整一波,如秒殺系統(tǒng), 在線商城, IM 即時(shí)通訊,Spring Cloud Alibaba 等等,戳我加入學(xué)習(xí),解鎖全部項(xiàng)目,已有1900+小伙伴加入

        • 1、數(shù)據(jù)冗余的方案
        • 2、解耦業(yè)務(wù)邏輯的數(shù)據(jù)同步方案
        • 3、最終效果

        曾經(jīng)設(shè)計(jì)的一個(gè)供應(yīng)鏈系統(tǒng)中,存在商品 、銷售訂單采購 這三個(gè)服務(wù),它們的主數(shù)據(jù)的部分結(jié)構(gòu)如下所示:

        商品

        ID 名稱 分類 型號 生產(chǎn)年份 編碼






        訂單和子訂單

        訂單ID 下單時(shí)間 客戶 總金額 子訂單ID 商品ID 單價(jià) 數(shù)量








        采購單和子訂單

        采購單ID 下單時(shí)間 供應(yīng)商 總金額 采購子訂單ID 商品ID 單價(jià) 數(shù)量








        在設(shè)計(jì)這個(gè)供應(yīng)鏈系統(tǒng)時(shí),我們需要滿足以下兩個(gè)需求:

        • 根據(jù)商品的型號/分類/生成年份/編碼 等查找訂單;
        • 根據(jù)商品的型號/分類/生成年份/編碼 等查找采購訂單。

        初期我們的方案是這樣設(shè)計(jì)的:嚴(yán)格按照的微服務(wù)劃分原則將商品相關(guān)的職責(zé)存放在商品系統(tǒng)中。因此,在查詢訂單與采購單時(shí),如果查詢字段包含商品字段,我們需要按照如下順序進(jìn)行查詢:

        • 先根據(jù)商品字段調(diào)用商品的服務(wù),然后返回匹配的商品信息;
        • 在訂單或采購單中,通過 IN 語句匹配商品 ID,再關(guān)聯(lián)查詢對應(yīng)的單據(jù)。

        為了方便理解這個(gè)過程,訂單查詢流程圖如下圖所示:

        圖片

        初期方案設(shè)計(jì)完后,很快我們就遇到了一系列問題:

        • 隨著商品數(shù)量的增多,匹配的商品越來越多,于是訂單服務(wù)中包含 IN 語句的查詢效率越來越慢
        • 商品作為一個(gè)核心服務(wù),依賴它的服務(wù)越來越多,同時(shí)隨著商品數(shù)據(jù)量的增長,商品服務(wù)已不堪重負(fù),響應(yīng)速度也變慢,還存在請求超時(shí) 的情況
        • 由于商品服務(wù)超時(shí),相關(guān)服務(wù)處理請求經(jīng)常失敗。

        結(jié)果就是業(yè)務(wù)方每次查詢訂單或采購單時(shí),只要帶上了商品這個(gè)關(guān)鍵字,查詢效率就會(huì)很慢而且老是失敗。于是,我們重新想了一個(gè)新方案——數(shù)據(jù)冗余 ,下面我們一起來看下。

        1、數(shù)據(jù)冗余的方案

        數(shù)據(jù)冗余說白了就是在訂單、采購單中保存一些商品字段 信息。

        為了方便理解,我們借助上面實(shí)際業(yè)務(wù)場景具體說明下,看看兩者的區(qū)別。

        商品

        ID 名稱 分類ID 型號 生產(chǎn)年份ID 編碼






        訂單和子訂單

        訂單ID 下單時(shí)間 客戶 總金額



        子訂單ID 商品ID 單價(jià) 數(shù)量 商品名稱 商品分類ID 商品型號 生產(chǎn)批次ID

        采購單和子訂單

        采購單ID 下單時(shí)間 供應(yīng)商 總金額



        采購子訂單ID 商品ID 單價(jià) 數(shù)量 商品名稱 商品分類ID 商品型號 生產(chǎn)批次ID

        調(diào)整架構(gòu)方案后,每次查詢時(shí),我們就可以不再依賴商品服務(wù)了 。

        但是,如果商品進(jìn)行了更新,我們?nèi)绾瓮饺哂嗟臄?shù)據(jù)呢?在此分享2種 解決辦法。

        1. 每次更新商品時(shí),先調(diào)用訂單與采購服務(wù),再更新商品的冗余數(shù)據(jù)。
        2. 每次更新商品時(shí),先發(fā)布一條消息,訂單與采購服務(wù)各自訂閱這條消息后,再各自更新商品冗余數(shù)據(jù)。

        那么這2種方案會(huì)出現(xiàn)哪些問題呢?

        如果商品服務(wù)每次更新商品都要調(diào)用訂單與采購服務(wù),然后再更新冗余數(shù)據(jù),則會(huì)出現(xiàn)以下兩種問題。

        • 數(shù)據(jù)一致性問題 :如果訂單與采購的冗余數(shù)據(jù)更新失敗了,整個(gè)操作都需要回滾。這時(shí)商品服務(wù)的開發(fā)人員肯定不樂意,因?yàn)槿哂鄶?shù)據(jù)不是商品服務(wù)的核心需求,不能因?yàn)檫吘壛鞒套钄嗔俗陨淼暮诵牧鞒獭?
        • 依賴問題 :從職責(zé)來說,商品服務(wù)應(yīng)該只關(guān)注商品本身,但是現(xiàn)在商品還需要調(diào)用訂單與采購服務(wù)。而且,依賴商品這個(gè)核心服務(wù)的服務(wù)實(shí)在是太多了,也就導(dǎo)致后續(xù)商品服務(wù)每次更新商品時(shí),都需要調(diào)用更新訂單冗余數(shù)據(jù)、更新采購冗余數(shù)據(jù)、更新門店庫存冗余數(shù)據(jù)、更新運(yùn)營冗余數(shù)據(jù)等一大堆服務(wù)。那么商品到底是下游服務(wù)還是上游服務(wù)?還能不能安心當(dāng)?shù)讓雍诵姆?wù)?

        因此,第一個(gè)解決辦法直接被我們否決了,即我們采取的第二個(gè)解決辦法——通過消息發(fā)布訂閱的方案 ,因?yàn)樗嬖谌缦?2 點(diǎn) 優(yōu)勢:

        • 商品無須調(diào)用其他服務(wù),它只需要關(guān)注自身邏輯即可,頂多多生成一條消息送到 MQ 。
        • 如果訂單、采購等服務(wù)的更新冗余數(shù)據(jù)失敗了,我們使用消息重試機(jī)制 就可以了,最終能保證數(shù)據(jù)的一致性。

        此時(shí),我們的架構(gòu)方案如下圖所示:

        圖片

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

        1、在這個(gè)方案中,僅僅保存冗余數(shù)據(jù)還遠(yuǎn)遠(yuǎn)不夠,我們還需要將商品分類與生產(chǎn)批號的清單進(jìn)行關(guān)聯(lián)查詢。也就是說,每個(gè)服務(wù)不只是訂閱商品變更這一種消息,還需要訂閱商品分類、商品生產(chǎn)批號變更等消息。下面請注意查看訂單表結(jié)構(gòu)的紅色加粗部分內(nèi)容。

        訂單ID 下單時(shí)間 客戶 總金額



        子訂單ID 商品ID 單價(jià) 數(shù)量 商品名稱 商品分類ID 商品型號 生產(chǎn)批次ID

        以上只是列舉了一部分的結(jié)構(gòu),事實(shí)上,商品表中還有很多字段存在冗余,比如保修類型、包換類型等。為了更新這些冗余數(shù)據(jù),采購服務(wù)與訂單服務(wù)往往需要訂閱近十種消息,因此,我們基本上需要把商品的一小半邏輯復(fù)制過來。

        2、每個(gè)依賴的服務(wù)需要重復(fù)實(shí)現(xiàn)冗余數(shù)據(jù)更新同步的邏輯。前面我們講了采購、訂單及其他服務(wù)都需要依賴商品數(shù)據(jù),因此每個(gè)服務(wù)需要將冗余數(shù)據(jù)的訂閱、更新邏輯做一遍,最終重復(fù)的代碼就會(huì)很多。

        3、MQ 消息類型太多了:聯(lián)調(diào)時(shí)最麻煩的是 MQ 之間的聯(lián)動(dòng),如果是接口聯(lián)調(diào)還好說,因?yàn)檎{(diào)用哪個(gè)服務(wù)器的接口相對可控而且比較好追溯;如果是消息聯(lián)調(diào)就比較麻煩,因?yàn)槲覀兂32恢滥硹l消息被哪臺(tái)服務(wù)節(jié)點(diǎn)消費(fèi)了,為了讓特定的服務(wù)器消費(fèi)特定的消息,我們就需要臨時(shí)改動(dòng)雙方的代碼。不過聯(lián)調(diào)完成后,我們經(jīng)常忘了改回原代碼。

        為此,我們不希望針對冗余數(shù)據(jù)這種非核心需求出現(xiàn)如此多的問題,最終決定使用一個(gè)特別的同步冗余數(shù)據(jù)方案,接下來我們進(jìn)一步說明。

        2、解耦業(yè)務(wù)邏輯的數(shù)據(jù)同步方案

        解耦業(yè)務(wù)邏輯的數(shù)據(jù)同步方案的設(shè)計(jì)思路是這樣的:

        • 將商品及商品相關(guān)的一些表(比如分類表、生產(chǎn)批號表、保修類型、包換類型等)實(shí)時(shí)同步到需要依賴使用它們的服務(wù)的數(shù)據(jù)庫,并且保持表結(jié)構(gòu)不變;
        • 在查詢采購、訂單等服務(wù)時(shí),直接關(guān)聯(lián)同步過來的商品相關(guān)表;
        • 不允許采購、訂單等服務(wù)修改商品相關(guān)表。

        此時(shí),整個(gè)方案的架構(gòu)如下圖所示:

        圖片

        以上方案就能輕松解決如下兩個(gè)問題:

        • 商品無須依賴其他服務(wù),如果其他服務(wù)的冗余數(shù)據(jù)同步失敗,它也不需要回滾自身的流程;
        • 采購、訂單等服務(wù)無須關(guān)注冗余數(shù)據(jù)的同步。

        不過,該方案的“缺點(diǎn) ”是增加了訂單、采購等數(shù)據(jù)庫的存儲(chǔ)空間(因?yàn)樵黾恿松唐废嚓P(guān)表)。

        仔細(xì)計(jì)算后,我們發(fā)現(xiàn)之前數(shù)據(jù)冗余的方案中每個(gè)訂單都需要保存一份商品的冗余數(shù)據(jù),假設(shè)訂單總數(shù)是 N,商品總數(shù)是 M,而 N 一般遠(yuǎn)遠(yuǎn)大于 M。因此,在之前數(shù)據(jù)冗余的方案中,N 條訂單就會(huì)產(chǎn)生 N 條商品的冗余數(shù)據(jù)。相比之下,解耦業(yè)務(wù)邏輯的數(shù)據(jù)同步方案更省空間,因?yàn)橹辉黾恿?M 條商品的數(shù)據(jù)。

        此時(shí)問題又來了,如何實(shí)時(shí)同步相關(guān)表的數(shù)據(jù)呢?

        我們直接找一個(gè)現(xiàn)成的開源中間件就可以了,不過它需要滿足支持實(shí)時(shí)同步、支持增量同步、不用寫業(yè)務(wù)邏輯、支持 MySQL 之間同步、活躍度高這五點(diǎn)要求。

        根據(jù)這五點(diǎn)要求,我們在市面上找了一圈,發(fā)現(xiàn)了 Canal 、Debezium 、DataX 、Databus 、Flinkx 、Bifrost 這幾款開源中間件,它們之間的區(qū)別如下表所示:

        圖片

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

        1. 它的界面管理不錯(cuò);
        2. 它的架構(gòu)比較簡單,出現(xiàn)問題后,我們可以自行調(diào)查,之后就算作者不維護(hù)了也可以自我維護(hù),相對比較可控。
        3. 作者更新活躍;
        4. 自帶監(jiān)控報(bào)警功能。

        因此,最終我們使用了 Bifrost 開源中間件,此時(shí)整個(gè)方案的架構(gòu)如下圖所示:

        圖片

        3、最終效果

        整個(gè)架構(gòu)方案上線后,商品數(shù)據(jù)的同步還算比較穩(wěn)定,此時(shí)商品服務(wù)的開發(fā)人員只需要關(guān)注自身邏輯,無須再關(guān)注使用數(shù)據(jù)的人。如果需要關(guān)聯(lián)使用商品數(shù)據(jù)的訂單,采購服務(wù)的開發(fā)人員也無須關(guān)注商品數(shù)據(jù)的同步問題,只需要在查詢時(shí)加上關(guān)聯(lián)語句即可,實(shí)現(xiàn)了雙贏。

        然而,唯一讓我們擔(dān)心的是 Bifrost 不支持集群,沒法保障高可用性。不過,到目前為止,它還沒有出現(xiàn)宕機(jī)的情況,反而是那些部署多臺(tái)節(jié)點(diǎn)負(fù)載均衡的后臺(tái)服務(wù)常常會(huì)出現(xiàn)宕機(jī)。

        最終,我們總算解決了服務(wù)之間數(shù)據(jù)依賴的問題。

        ?? 歡迎加入小哈的星球,你將獲得: 專屬的項(xiàng)目實(shí)戰(zhàn) / 1v1 提問 / Java 學(xué)習(xí)路線 / 學(xué)習(xí)打卡 / 每月贈(zèng)書 / 社群討論

        • 新項(xiàng)目:《從零手?jǐn)]:仿小紅書(微服務(wù)架構(gòu))》 正在持續(xù)爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17..., 點(diǎn)擊查看項(xiàng)目介紹;
        • 《從零手?jǐn)]:前后端分離博客項(xiàng)目(全棧開發(fā))》 2期已完結(jié),演示鏈接:http://116.62.199.48/;

        截止目前,累計(jì)輸出 54w+ 字,講解圖 2330+ 張,還在持續(xù)爆肝中.. 后續(xù)還會(huì)上新更多項(xiàng)目,目標(biāo)是將 Java 領(lǐng)域典型的項(xiàng)目都整一波,如秒殺系統(tǒng), 在線商城, IM 即時(shí)通訊,Spring Cloud Alibaba 等等,戳我加入學(xué)習(xí),解鎖全部項(xiàng)目,已有1900+小伙伴加入


            
               

        1. 我的私密學(xué)習(xí)小圈子~

        2. 船新 IDEA 2024.2 正式發(fā)布,新特性真香!

        3. 使用 Java + WebSocket 實(shí)現(xiàn)簡單實(shí)時(shí)雙人協(xié)同 pk 答題

        4. Java8 中一個(gè)極其強(qiáng)悍的新接口,很多人沒用過

        最近面試BAT,整理一份面試資料Java面試BATJ通關(guān)手冊,覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫、數(shù)據(jù)結(jié)構(gòu)等等。

        獲取方式:點(diǎn)“在看”,關(guān)注公眾號并回復(fù) Java 領(lǐng)取,更多內(nèi)容陸續(xù)奉上。

        PS:因公眾號平臺(tái)更改了推送規(guī)則,如果不想錯(cuò)過內(nèi)容,記得讀完點(diǎn)一下在看,加個(gè)星標(biāo),這樣每次新文章推送才會(huì)第一時(shí)間出現(xiàn)在你的訂閱列表里。

        點(diǎn)“在看”支持小哈呀,謝謝啦

        瀏覽 79
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評論
        圖片
        表情
        推薦
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
          
          

            1. 天天摸天天操天天日 | 久久久国产精品视频 | 中日韩无码视频 | 国产va精品免费观看 | 美女自慰网站免费 |