国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - java開發微服務架構設計消息隊列的水有多深

java開發微服務架構設計消息隊列的水有多深

2022-03-03 12:48飄渺Jam Java教程

今天我們說說消息隊列的問題,來帶大家探一探消息隊列的水有多深,希望看完本文大家在引入消息隊列的時候先想一想,是不是一定要引入?引入消息隊列后產生的問題能不能解決

很多人在做架構設計時往往會“過度設計”,簡單問題復雜化,上來就引一堆中間件,我想大概原因主要有下面兩點:

為了秀(學)技術而架構
我們常說技術是為業務服務的,不能為了技術而技術,為了秀技術引入一堆復雜架構這是要不得的。

考慮問題不全面,或者說廣度不夠,不知道如何簡單化
舉個栗子,假設有一個高并發的用戶平臺需要處理注冊(寫)及登錄查詢(讀)功能,在數據庫層做了主從同步。為了解決主從同步延時問題引入了一個Redis,想實現寫主庫的時候同時寫Redis,然后讀的時候直接讀Redis,這就避免了主從延時同步問題。這就是典型的考慮問題不全面,這樣雖然能解決主從延時問題,但是又會導致雙寫事務的產生,那為什么不直接把主從同步的方式改成強同步復制呢,這樣不是直接保證了一致性嗎?
那你可能會說改成強同步復制不是會增加響應時間進而影響系統吞吐量嗎,那咱還可以對用戶做個分庫,多做幾個主從同步出來不就可以了嗎?

誒誒誒,跑題了,今天咱不是說消息隊列嗎?

哦,言歸正傳。今天我們說說消息隊列的問題,希望看完本文大家在引入消息隊列的時候先想一想,是不是一定要引入?引入消息隊列后產生的問題能不能解決?

 

消息隊列的作用

在微服務開發中我們經常會引入消息中間件實現業務解耦,執行異步操作, 現在讓我們來看看使用消息中間件的好處和弊端。

首先需要肯定是使用消息組件有很多好處,其中最核心的三個是:解耦、異步、削峰。

  • 解耦:客戶端只要講請求發送給特定的通道即可,不需要感知接收請求實例的情況。
  • 異步:將消息寫入消息隊列,非必要的業務邏輯以異步的方式運行,加快響應速度。
  • 削峰:消息中間件在消息被消費之前一直緩存消息,消息處理端可以按照自己處理的并發量從消息隊列中慢慢處理消息,不會一瞬間壓垮業務。

當然消息中間件并不是銀彈,引入消息機制后也會有如下一些弊端:

  • 潛在的性能瓶頸:消息代理可能會存在性能瓶頸。幸運的是目前主流的消息中間件都支持高度的橫向擴展。
  • 潛在的單點故障:消息代理的高可用性至關重要,否則系統整體的可靠性將受到影響,幸運的是大多數消息中間件都是高可用的。
  • 額外的操作復雜性:消息系統是一個必須獨立安裝、配置和運維的系統組件,增加了運維的復雜度。

這些弊端我們借助消息中間件本身提供的擴展、高可用能力可以解決,但是要真正用好消息中間件我們還需要關注可能會遇到的一些設計難題。

 

消息隊列的設計難題

處理并發和順序消息

在生產環境中為了提高消息處理的能力以及應用程序的吞吐量,一般會將消費者部署多個實例節點。那么帶來的挑戰就是如何確保每個消息只被處理一次,并且是按照他們的發送順序來處理的。

例如:假設有3個相同的接收方實例從同一個點對點通道讀取消息,發送方按順序發布了 Order Created、Order Updated 和 Order Cancelled 這3個事件消息。簡單的消息實現可能就會同事講每個消息給不同的接收方。若由于網絡問題導致延遲,消息可能沒有按照他們發出時的順序被處理,這將導致奇怪的行為,服務實例可能在另一個服務器處理 Order Created 消息之前處理 Order Cancelled消息。

Kafka 使用的解決方案是使用分片(分區)通道。整體解決方案分為三個部分:

  • 一個主題通道由多個分片組成,每個分片的行為類似一個通道。
  • 發送方在消息頭部指定分片鍵如orderId,Kafka使用分片鍵將消息分配給特定的分片。
  • 將接收方的多個實例組合在一起,并將他們視為相同的邏輯接收方(消費者組)。kafka將每個分片分配給單個接收器,它在接收方啟動和關閉時重新分配分片。

java開發微服務架構設計消息隊列的水有多深

如上圖所示,每個Order事件消息都將orderId作為其分片鍵。特定訂單的每個事件都發布到同一個分片。而且該分片中的消息始終由同一個接收方實例讀取,因此這樣就能夠保證按順序處理這些消息。

處理重復消息

引入消息架構必須要解決的另一個挑戰是處理重復消息。在理想情況下,消息代理應該只傳遞一次消息,但保證消息有且僅有一次的消息傳遞的成本通常很高。相反,很多消息組件承諾至少保證成功傳遞一次消息。

在正常情況下,消息組件只會傳遞一次消息。但是當客戶端、網絡或消息組件故障可能導致消息被多次傳遞。假設客戶端在處理消息后發送確認消息前,他的數據庫崩潰了,這時消息組件將再次發送未確認的消息,在數據庫重新啟動時向該客戶端發送。

處理重復消息有以下兩種不同的方法:

編寫冪等消息處理程序

跟蹤消息并丟棄重復項

編寫冪等消息處理器

如果應用程序處理消息的邏輯是滿足冪等的,那么重復消息就是無害的。程序的冪等性是指,即使這個應用被相同輸入參數多次重復調用時,也不會產生額外的效果。例如:取消一個已經取消的訂單,就是一個冪等性操作。同樣,創建一個已經存在的訂單操作也必是這樣。滿足冪等的消息處理程序可以被放心的執行多次,只要消息組件在傳遞消息時保持相同的消息順序。

但是不幸的是,應用程序通常不是冪等的。或者你現在正在使用的消息組件在重新傳遞消息時不會保留排序。重復或無序消息可能會導致錯誤。在這種情況下,你需要編寫跟蹤消息并丟棄重復消息的消息處理程序。

跟蹤消息并丟棄重復消息

考慮一個授權消費者信用卡的消息處理程序。它必須為每個訂單僅執行一次信用卡授權操作。這段應用程序每次調用時都會產生不同的效果。如果重復消息導致消息處理程序多次執行該邏輯,則應用程序的行為將不正確。執行此類應用程序邏輯的消息處理程序必須通過檢測和丟棄重復消息而讓它成為冪等的。

一個簡單的解決方案是消息接收方使用 message id 跟蹤他已處理的消息并丟棄任何重復項。例如,在數據庫表中存儲它消費的每條消息的 message id。

java開發微服務架構設計消息隊列的水有多深

當接收方處理消息時,它將消息的 message id 作為創建和變更業務實體的事務的一部分記錄在數據表里。如上圖所示,接收方將包含message id 的行插入 PROCESSED_MESSAGE表。如果消息是重復的,則INSERT將失敗,接收方可以選擇丟棄該消息。

另一個解決方案是消息處理程序在應用程序表,而不是專門表中記錄 message id。當時用具有受限事務模型的NoSQL數據庫時,此方法特別有用,因為 NoSQL數據庫通常不支持將針對兩個表的更新作為數據庫事務。

處理事務性消息

服務通常需要在更新數據庫的事務中發布消息,數據庫更新和消息發送都必須在事務中進行,否則服務可能會更新數據庫然后在發送消息之前崩潰。

如果服務不以原子方式執行者兩個操作,則類似的故障可能使系統處于不一致狀態。

接下來我們看一下常用的保證事務消息的兩種解決方案,最后再看看現代消息組件RocketMQ的事務性消息解決方案。

使用數據庫表作為消息隊列

如果你的應用程序正在使用關系型數據庫,要保證數據的更新和消息發送之間的事務可以直接使用事務性發件箱模式,Transactional Outbox。

java開發微服務架構設計消息隊列的水有多深

此模式使用數據庫表作為臨時消息隊列。如上圖所示,發送消息的服務有個OUTBOX數據表,在進行INSERT、UPDATE、DELETE 業務操作時也會給OUTBOX數據表INSERT一條消息記錄,這樣可以保證原子性,因為這是基于本地的ACID事務。

OUTBOX表充當臨時消息隊列,然后我們在引入一個消息中繼(MessageRelay)的服務,由他從OUTBOX表中讀取數據并發布消息到消息組件。

消息中繼的實現可以很簡單,只需要通過定時任務定期從OUTBOX表中拉取最新未發布的數據,獲取到數據后將數據發送給消息組件,最后將完成發送的消息從OUTBOX表中刪除即可。

使用事務日志發布事件

另外一種保證事務性消息的方式是基于數據庫的事務日志,也就是所謂的數據變更捕獲,Change Data Capture,簡稱CDC。

一般數據庫在數據發生變更的時候都會記錄事務日志(Transaction Log),比如MySQL的binlog。事務日志可以簡單的理解成數據庫本地的一個文件隊列,它主要記錄按時間順序發生的數據庫表變更記錄。

這里我們利用alibaba開源的組件canal結合MySQL來說明下這種模式的工作原理。

更多操作說明可以參考官方文檔:https://github.com/alibaba/canal

canal工作原理

canal 模擬 MySQL slave 的交互協議,把自己偽裝成一個MySQL的 slave節點 ,向 MySQL master 發送dump 協議;

MySQL master 收到 dump 請求,開始推送 binary log 給 slave (即 canal );

canal 解析 binary log 對象(原始為 byte 流),然后可以將解析后的數據直接發送給消息組件。

RocketMQ事務消息解決方案

Apache RocketMQ在4.3.0版中已經支持分布式事務消息,RocketMQ采用了2PC的思想來實現了提交事務消息,同時增加一個補償邏輯來處理二階段超時或者失敗的消息,如下圖所示。

java開發微服務架構設計消息隊列的水有多深

RocketMQ實現事務消息主要分為兩個階段:正常事務的發送及提交、事務信息的補償流程。

整體流程為:

正常事務發送與提交階段
1、生產者發送一個半消息給MQServer(半消息是指消費者暫時不能消費的消息)
2、服務端響應消息寫入結果,半消息發送成功
3、開始執行本地事務
4、根據本地事務的執行狀態執行Commit或者Rollback操作

事務信息的補償流程
1、如果MQServer長時間沒收到本地事務的執行狀態會向生產者發起一個確認回查的操作請求
2、生產者收到確認回查請求后,檢查本地事務的執行狀態
3、根據檢查后的結果執行Commit或者Rollback操作
補償階段主要是用于解決生產者在發送Commit或者Rollback操作時發生超時或失敗的情況。

在生產者使用RocketMQ發送事務消息的時候我們也會借鑒第一種方案即自建一張事務日志表,然后在執行本地事務的時候同時生成一條事務日志記錄,讓本地事務與日志事務在同一個方法中,同時添加 @Transactional 注解,保證兩個操作事務是一個原子操作。這樣如果事務日志表中有這個本地事務的信息,那就代表本地事務執行成功,需要Commit,相反如果沒有對應的事務日志,則表示沒執行成功,需要Rollback。

孩砸,看完這篇文章,消息隊列你能把握住了嗎?

以上就是java開發之微服務架構消息隊列的水有多深的詳細內容,更多關于微服務架構消息隊列的資料請關注服務器之家其它相關文章!

原文鏈接:https://jianzh5.blog.csdn.net/article/details/117018102

延伸 · 閱讀

精彩推薦
  • Java教程利用Java8 Optional如何避免空指針異常詳解

    利用Java8 Optional如何避免空指針異常詳解

    Optional可以讓你的代碼具有可讀性,且會避免出現空指針異常。 下面這篇文章主要給大家介紹了關于利用Java8 Optional如何避免空指針異常的相關資料,文中...

    劉亞濤6472021-03-18
  • Java教程例舉fastJson和jackson轉json的區別

    例舉fastJson和jackson轉json的區別

    今天小編就為大家分享一篇關于例舉fastJson和jackson轉json的區別,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編...

    執筆記憶的空白11732021-06-21
  • Java教程淺談Mybatis SqlSession執行流程

    淺談Mybatis SqlSession執行流程

    本文主要介紹了淺談Mybatis SqlSession執行流程,文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學習學習吧...

    Java有貨6902021-10-03
  • Java教程Java練手小項目實現一個項目管理系統

    Java練手小項目實現一個項目管理系統

    讀萬卷書不如行萬里路,只學書上的理論是遠遠不夠的,只有在實戰中才能獲得能力的提升,本篇文章手把手帶你用Java實現一個項目管理系統,大家可以在...

    空山新雨后~10222022-02-24
  • Java教程Java反射機制的講解

    Java反射機制的講解

    今天小編就為大家分享一篇關于Java反射機制的講解,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧...

    yangyongUestc4382021-07-31
  • Java教程我從jdk1.8升級到jdk11所遇到的坑都有這些

    我從jdk1.8升級到jdk11所遇到的坑都有這些

    這篇文章主要介紹了從jdk1.8升級到jdk11將會遇到的一些坑,本文給大家分享解決方案對大家的學習或工作具有參考借鑒價值,對jdk1.8升級到jdk11相關知識感興...

    AI碼師5042021-11-22
  • Java教程Java的方法和this關鍵字如何理解與應用

    Java的方法和this關鍵字如何理解與應用

    Java語言中的“方法”(Method)在其他語言當中也可能被稱為“函數”(Function)。對于一些復雜的代碼邏輯,如果希望重復使用這些代碼,并且做到“隨時...

    spring小楊11272022-02-15
  • Java教程java中ZXing 生成、解析二維碼圖片的小示例

    java中ZXing 生成、解析二維碼圖片的小示例

    ZXing 是一個開源 Java 類庫用于解析多種格式的 1D/2D 條形碼,這篇文章主要介紹了java中ZXing 生成、解析二維碼圖片的小示例 ,有興趣的可以了解一下。...

    靜默虛空2282020-07-27
主站蜘蛛池模板: 精品亚洲成a人在线观看 | 亚洲成人精品一区 | 精品1区| 久久久国产精品一区 | 日韩激情一区二区三区 | 亚洲一区二区三区在线免费观看 | 国产黄色精品 | 在线黄av | 中文字幕人成乱码在线观看 | 欧美a在线看 | 九色网址 | 中文字幕 在线观看 | 欧美日韩国产一区 | 中文精品在线 | 男人午夜视频在线观看 | 日韩国产欧美视频 | 一区欧美| 午夜成人免费电影 | 亚洲一区 日韩精品 中文字幕 | 国产99久久 | 日韩欧美专区 | 中文字幕一区二区在线观看 | 日本精品中文字幕 | 亚洲男人皇宫 | 亚洲欧美在线观看视频 | 欧美成人精品一区二区三区 | 中文二区 | 成人日韩 | 日韩av福利 | 看片久久| 毛片a级 | 中文字幕三区 | 成人片免费看 | 日韩高清国产一区在线 | 亚洲一区在线日韩在线深爱 | 日韩超级大片免费看国产国产播放器 | 亚洲字幕成人中文在线观看 | 无码一区二区三区视频 | 中文字幕精品视频 | a国产精品 | www.成人在线视频 |