聊聊業務系統中投遞消息到mq的幾種方式

来源:https://www.cnblogs.com/itsoku123/archive/2019/05/05/10813423.html
-Advertisement-
Play Games

背景 電商中有這樣的一個場景: 1. 下單成功之後送積分的操作,我們使用mq來實現 2. 下單成功之後,投遞一條消息到mq,積分系統消費消息,給用戶增加積分 我們主要討論一下,下單及投遞消息到mq的操作,如何實現?每種方式優缺點? 方式一 step1:start transaction step2: ...


背景

電商中有這樣的一個場景:

  1. 下單成功之後送積分的操作,我們使用mq來實現
  2. 下單成功之後,投遞一條消息到mq,積分系統消費消息,給用戶增加積分

我們主要討論一下,下單及投遞消息到mq的操作,如何實現?每種方式優缺點?

方式一

step1:start transaction
step2:生成訂單
step3:投遞消息到mq
step4:commit transaction

這種方式是將發送消息放在了事務提交之前,可能存在的問題:

step3發生異常

導致step4失敗,下單失敗,直接影響到下單業務

step4發生異常,其他step成功

下單失敗,消息投遞成功,給用戶增加了積分

方式二

我們將發送消息放到事務之後進行:
step1:start transaction
step2:生成訂單
step3:commit transaction
step4:投遞消息到mq

可能會出現的問題:
step4發生異常,其他step成功

導致下單成功,投遞消息失敗,用戶未增加積分

上面兩種是比較常見的做法,也是最容易出錯的。

方式三

step1:start transaction
step2:生成訂單
step3:本地庫中插入一條需要發送消息的記錄t_msg_record
step3:commit transaction
step5:新增一個定時器,輪詢t_msg_record,將待發送的記錄投遞到mq中

這種方式藉助了資料庫的事務,業務和消息記錄作為了一個原子操作,業務成功之後,消息日誌必定是存在的。解決了前兩種方式遇到的問題。如果我們的業務系統比較單一,可以採用這種方式。

對於微服務化的情況,上面這種方式不是太好,每個服務都需要上面的操作;也不利於擴展。

方式四

增加一個消息服務消息庫,負責消息的落庫、將消息發送投遞到mq。

step1:start transaction
step2:生成訂單
step3:當前事務庫插入一條日誌:生成一個唯一的業務id(bus_id),將bus_id和訂單關聯起來保存到當前事務所在的庫中
step4:調用消息服務:攜帶bus_id,將消息先落地入庫,此時消息的狀態為待發送狀態,返回消息id(msg_id)
step5:commit transaction
step6:如果上面都成功,調用消息服務,將消息投遞到mq中;如果上面有失敗的情況,則調用消息服務取消消息的發送

能想到上面這種方式,已經算是有很大進步了,我們繼續分析一下可能存在的問題:

  1. 系統中增加了一個消息服務,下單操作依賴於該服務,業務對改服務依賴性比較高,當消息服務不可用時,整個業務將不可用。
  2. 若step6失敗,消息將處於待發送狀態,此時業務方需要提供一個會查介面(通過bus_id查詢),驗證業務是否執行成功;消息服務需新增一個定時任務,對於狀態為待發送狀態的消息做補償處理,檢查一下業務是否處理成功;從而確定消息是投遞還是取消發送
  3. step4依賴於消息服務,如果消息服務性能不佳,會導致當前業務的事務提交時間延長,容易產生死鎖,並導致併發性能降低。我們通常是比較忌諱在事務中做遠程調用處理的,遠程調用的性能和時間往往不可控,會導致當前事務變為一個大事務,從而引發其他故障。

方式五

在以上方式中,我們繼續改進,進而出現了更好的一種方式:

step1:生成一個全局唯一業務消息id(bus_msg_id),調用消息服務,攜帶bus_msg_id,將消息先落地入庫,此時消息的狀態為待發送狀態,返回消息id(msg_id)
step2:start transaction
step3:生成訂單
step4:當前事務庫插入一條日誌(將step3中的業務和bus_msg_id關聯起來)
step5:commit transaction
step6:分2中情況:如果上面都成功,調用消息服務,將消息投遞到mq中;如果上面有失敗的情況,則調用消息服務取消消息的發送

方式五和方式四對比,比較好的一個地方:將調用消息服務,消息落地操作,放在了事務之外進行,這點小的改進其實算是一個非常好的優化。

總結

  1. 若我們的系統系統比較小比較單一簡單,建議採用方式三
  2. 若我們的系統採用微服務的方式,建議使用方式五
  3. 你們的系統中如何發送消息的,大家可以留言,我們一起討論,一起進步。

mq系列整個內容

  1. 聊聊mq的使用場景
  2. 聊聊業務系統中投遞消息到mq的幾種方式
  3. 如何確保投遞消息一定成功?
  4. 聊聊消息消費的幾種方式
  5. 如何確保消息至少消費一次
  6. 如何保證消息消費的冪等性

路人甲Java,只生產乾貨,公眾號:javacode2018,喜歡的關註一下。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.官網下載msi文件安裝 2.多版本安裝 -1.卸載已有node -2.安裝nvm -在磁碟創建根目錄 -在根目錄下創建兩個子目錄(nodejs、nvm) -將下載的nvm.zip解壓到nvm目錄,運行install.cmd回車,配置生成文件,另存為當前目錄 -root: 修改為當前路徑 -pat ...
  • 頁面執行location.reload()刷新後需要執行的操作就沒法執行了。因為頁面刷新,代碼從頭執行 上網搜了好久,發現本地緩存可以解決,方法如下: localStorage.setItem(key,value):將value存儲到key欄位,本地緩存 localStorage.getItem(k ...
  • jquery的浪漫 主要用到知識點: 滑鼠事件onmousedown() onmousemove() onmouseup() jquery的運用,對dom元素的增刪改查 css3 3d 功能的靈活運用 實現的功能 跑馬燈效果 文字自動輸入 雪花飄落 滑鼠點擊 滑動生成雪花 背景音樂等 看效果 htm ...
  • 好幾天沒有更新了,直接上效果吧,哈哈!(我想這個應該大部分都會!哈哈哈!) 代碼如下: html: css: 大家一起努力吧!! ...
  • ```js class TrieNode { constructor(data){ this.data = data this.children = new Array(26) this.isEndingChar = false this.text = '' } } class TrieTree {... ...
  • 如果第二次看到我的文章,歡迎右側掃碼訂閱我喲~ 👉 每周五早8點 按時送達。當然了,也會時不時加個餐~ Z哥在前面的三篇文章里和你一起聊了「高性能」主題下與「緩存」相關的內容。這次和你來聊聊提高性能的另一個大招——「非同步」。 如果你已經對「非同步」有所瞭解的話,這次可以讓你有更深刻的理解。如果你對「 ...
  • [TOC] 一. 簡述一致性哈希演算法 這裡不詳細介紹一致性哈希演算法的起源了, 網上能方便地搜到許多介紹一致性哈希演算法的好文章. 本文主要想動手實現一致性哈希演算法, 並搭建一個環境進行實戰測試. 在開始之前先整理一下 演算法的思路 : 一致性哈希演算法通過把每台伺服器的哈希值打在哈希環上, 把哈希環分成不 ...
  • const:靜態常量,也稱編譯時常量(compile-time constants),屬於類型級,通過類名直接訪問,被所有對象共用! a、叫編譯時常量的原因是它編譯時會將其替換為所對應的值; b、靜態常量在速度上會稍稍快一些,但是靈活性卻比動態常量差一些; c、靜態常量,隱式是靜態的,即被stati ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...