1. 程式人生 > >分散式之訊息佇列精講

分散式之訊息佇列精講

為什麼使用訊息佇列?
使用訊息佇列有什麼缺點?
訊息佇列如何選型?
如何保證訊息佇列是高可用的?
如何保證訊息不被重複消費?
如何保證消費的可靠性傳輸?
如何保證訊息的順序性?
我們圍繞以上七點進行闡述。需要說明一下,本文不是《訊息佇列從入門到精通》這種課程,因此只是提供一個複習思路,而不是去教你們怎麼呼叫訊息佇列的API。建議對訊息佇列不瞭解的人,去找點訊息佇列的部落格看看,再看本文,收穫更大

正文
1、為什麼要使用訊息佇列?
分析:一個用訊息佇列的人,不知道為啥用,這就有點尷尬。沒有複習這點,很容易被問蒙,然後就開始胡扯了。
回答:這個問題,咱只答三個最主要的應用場景(不可否認還有其他的,但是隻答三個主要的),即以下六個字:解耦、非同步、削峰

(1)解耦
傳統模式:

傳統模式的缺點:

系統間耦合性太強,如上圖所示,系統A在程式碼中直接呼叫系統B和系統C的程式碼,如果將來D系統接入,系統A還需要修改程式碼,過於麻煩!
中介軟體模式:

中介軟體模式的的優點:

將訊息寫入訊息佇列,需要訊息的系統自己從訊息佇列中訂閱,從而系統A不需要做任何修改。
(2)非同步
傳統模式:

傳統模式的缺點:

一些非必要的業務邏輯以同步的方式執行,太耗費時間。
中介軟體模式:

中介軟體模式的的優點:

將訊息寫入訊息佇列,非必要的業務邏輯以非同步的方式執行,加快響應速度
(3)削峰
傳統模式

傳統模式的缺點:

併發量大的時候,所有的請求直接懟到資料庫,造成資料庫連線異常
中介軟體模式:

中介軟體模式的的優點:

系統A慢慢的按照資料庫能處理的併發量,從訊息佇列中慢慢拉取訊息。在生產中,這個短暫的高峰期積壓是允許的。
2、使用了訊息佇列會有什麼缺點?
分析:一個使用了MQ的專案,如果連這個問題都沒有考慮過,就把MQ引進去了,那就給自己的專案帶來了風險。我們引入一個技術,要對這個技術的弊端有充分的認識,才能做好預防。要記住,不要給公司挖坑!
回答:回答也很容易,從以下兩個個角度來答

系統可用性降低:你想啊,本來其他系統只要執行好好的,那你的系統就是正常的。現在你非要加個訊息佇列進去,那訊息佇列掛了,你的系統不是呵呵了。因此,系統可用性降低
系統複雜性增加:要多考慮很多方面的問題,比如一致性問題、如何保證訊息不被重複消費,如何保證保證訊息可靠傳輸。因此,需要考慮的東西更多,系統複雜性增大。
但是,我們該用還是要用的。

3、訊息佇列如何選型?
先說一下,博主只會ActiveMQ,RabbitMQ,RocketMQ,Kafka,對什麼ZeroMQ等其他MQ沒啥理解,因此只能基於這四種MQ給出回答。
分析:既然在專案中用了MQ,肯定事先要對業界流行的MQ進行調研,如果連每種MQ的優缺點都沒了解清楚,就拍腦袋依據喜好,用了某種MQ,還是給專案挖坑。如果面試官問:”你為什麼用這種MQ?。”你直接回答”領導決定的。”這種回答就很LOW了。還是那句話,不要給公司挖坑。
回答:首先,咱先上ActiveMQ的社群,看看該MQ的更新頻率:

Apache ActiveMQ 5.15.3 Release
Christopher L. Shannon posted on Feb 12, 2018
Apache ActiveMQ 5.15.2 Released
Christopher L. Shannon posted on Oct 23, 2017
Apache ActiveMQ 5.15.0 Released
Christopher L. Shannon posted on Jul 06, 2017
省略以下記錄

我們可以看出,ActiveMq幾個月才發一次版本,據說研究重心在他們的下一代產品Apollo。
接下來,我們再去RabbitMQ的社群去看一下,RabbitMQ的更新頻率

RabbitMQ 3.7.3 release 30 January 2018
RabbitMQ 3.6.15 release 17 January 2018
RabbitMQ 3.7.2 release23 December 2017
RabbitMQ 3.7.1 release21 December 2017
省略以下記錄

我們可以看出,RabbitMQ版本釋出比ActiveMq頻繁很多。至於RocketMQ和kafka就不帶大家看了,總之也比ActiveMQ活躍的多。詳情,可自行查閱。
再來一個效能對比表

特性 ActiveMQ RabbitMQ RocketMQ kafka
開發語言 java erlang java scala
單機吞吐量 萬級 萬級 10萬級 10萬級
時效性 ms級 us級 ms級 ms級以內
可用性 高(主從架構) 高(主從架構) 非常高(分散式架構) 非常高(分散式架構)
功能特性 成熟的產品,在很多公司得到應用;有較多的文件;各種協議支援較好 基於erlang開發,所以併發能力很強,效能極其好,延時很低;管理介面較豐富 MQ功能比較完備,擴充套件性佳 只支援主要的MQ功能,像一些訊息查詢,訊息回溯等功能沒有提供,畢竟是為大資料準備的,在大資料領域應用廣。
綜合上面的材料得出以下兩點:
(1)中小型軟體公司,建議選RabbitMQ.一方面,erlang語言天生具備高併發的特性,而且他的管理介面用起來十分方便。正所謂,成也蕭何,敗也蕭何!他的弊端也在這裡,雖然RabbitMQ是開源的,然而國內有幾個能定製化開發erlang的程式設計師呢?所幸,RabbitMQ的社群十分活躍,可以解決開發過程中遇到的bug,這點對於中小型公司來說十分重要。不考慮rocketmq和kafka的原因是,一方面中小型軟體公司不如網際網路公司,資料量沒那麼大,選訊息中介軟體,應首選功能比較完備的,所以kafka排除。不考慮rocketmq的原因是,rocketmq是阿里出品,如果阿里放棄維護rocketmq,中小型公司一般抽不出人來進行rocketmq的定製化開發,因此不推薦。
(2)大型軟體公司,根據具體使用在rocketMq和kafka之間二選一。一方面,大型軟體公司,具備足夠的資金搭建分散式環境,也具備足夠大的資料量。針對rocketMQ,大型軟體公司也可以抽出人手對rocketMQ進行定製化開發,畢竟國內有能力改JAVA原始碼的人,還是相當多的。至於kafka,根據業務場景選擇,如果有日誌採集功能,肯定是首選kafka了。具體該選哪個,看使用場景。

4、如何保證訊息佇列是高可用的?
分析:在第二點說過了,引入訊息佇列後,系統的可用性下降。在生產中,沒人使用單機模式的訊息佇列。因此,作為一個合格的程式設計師,應該對訊息佇列的高可用有很深刻的瞭解。如果面試的時候,面試官問,你們的訊息中介軟體如何保證高可用的?你的回答只是表明自己只會訂閱和釋出訊息,面試官就會懷疑你是不是隻是自己搭著玩,壓根沒在生產用過。請做一個愛思考,會思考,懂思考的程式設計師。
回答:這問題,其實要對訊息佇列的叢集模式要有深刻了解,才好回答。
以rcoketMQ為例,他的叢集就有多master 模式、多master多slave非同步複製模式、多 master多slave同步雙寫模式。多master多slave模式部署架構圖(網上找的,偷個懶,懶得畫):
image
其實博主第一眼看到這個圖,就覺得和kafka好像,只是NameServer叢集,在kafka中是用zookeeper代替,都是用來儲存和發現master和slave用的。通訊過程如下:
Producer 與 NameServer叢集中的其中一個節點(隨機選擇)建立長連線,定期從 NameServer 獲取 Topic 路由資訊,並向提供 Topic 服務的 Broker Master 建立長連線,且定時向 Broker 傳送心跳。Producer 只能將訊息傳送到 Broker master,但是 Consumer 則不一樣,它同時和提供 Topic 服務的 Master 和 Slave建立長連線,既可以從 Broker Master 訂閱訊息,也可以從 Broker Slave 訂閱訊息。
那麼kafka呢,為了對比說明直接上kafka的拓補架構圖(也是找的,懶得畫)
image
如上圖所示,一個典型的Kafka叢集中包含若干Producer(可以是web前端產生的Page View,或者是伺服器日誌,系統CPU、Memory等),若干broker(Kafka支援水平擴充套件,一般broker數量越多,叢集吞吐率越高),若干Consumer Group,以及一個Zookeeper叢集。Kafka通過Zookeeper管理叢集配置,選舉leader,以及在Consumer Group發生變化時進行rebalance。Producer使用push模式將訊息釋出到broker,Consumer使用pull模式從broker訂閱並消費訊息。
至於rabbitMQ,也有普通叢集和映象叢集模式,自行去了解,比較簡單,兩小時即懂。
要求,在回答高可用的問題時,應該能邏輯清晰的畫出自己的MQ叢集架構或清晰的敘述出來。

5、如何保證訊息不被重複消費?
分析:這個問題其實換一種問法就是,如何保證訊息佇列的冪等性?這個問題可以認為是訊息佇列領域的基本問題。換句話來說,是在考察你的設計能力,這個問題的回答可以根據具體的業務場景來答,沒有固定的答案。
回答:先來說一下為什麼會造成重複消費?
  其實無論是那種訊息佇列,造成重複消費原因其實都是類似的。正常情況下,消費者在消費訊息時候,消費完畢後,會發送一個確認資訊給訊息佇列,訊息佇列就知道該訊息被消費了,就會將該訊息從訊息佇列中刪除。只是不同的訊息佇列傳送的確認資訊形式不同,例如RabbitMQ是傳送一個ACK確認訊息,RocketMQ是返回一個CONSUME_SUCCESS成功標誌,kafka實際上有個offset的概念,簡單說一下(如果還不懂,出門找一個kafka入門到精通教程),就是每一個訊息都有一個offset,kafka消費過訊息後,需要提交offset,讓訊息佇列知道自己已經消費過了。那造成重複消費的原因?,就是因為網路傳輸等等故障,確認資訊沒有傳送到訊息佇列,導致訊息佇列不知道自己已經消費過該訊息了,再次將該訊息分發給其他的消費者。
  如何解決?這個問題針對業務場景來答分以下幾點
  (1)比如,你拿到這個訊息做資料庫的insert操作。那就容易了,給這個訊息做一個唯一主鍵,那麼就算出現重複消費的情況,就會導致主鍵衝突,避免資料庫出現髒資料。
  (2)再比如,你拿到這個訊息做redis的set的操作,那就容易了,不用解決,因為你無論set幾次結果都是一樣的,set操作本來就算冪等操作。
  (3)如果上面兩種情況還不行,上大招。準備一個第三方介質,來做消費記錄。以redis為例,給訊息分配一個全域性id,只要消費過該訊息,將

相關推薦

分散式訊息佇列

為什麼使用訊息佇列? 使用訊息佇列有什麼缺點? 訊息佇列如何選型? 如何保證訊息佇列是高可用的? 如何保證訊息不被重複消費? 如何保證消費的可靠性傳輸? 如何保證訊息的順序性? 我們圍繞以上七點進行闡述。需要說明一下,本文不是《訊息佇列從入門到精通

分散式訊息佇列複習

文章轉自www.cnblogs.com/rjzheng/p/8994962.html 引言 為什麼寫這篇文章? 博主有兩位朋友分別是小A和小B: 小A,工作於傳統軟體行業(某社保局的軟體外包公司),每天工作內容就是和產品聊聊需求,改改業務邏輯。再不然就是和運營

Java程式設計師從笨鳥到菜鳥(五十四) 分散式訊息佇列

##目錄 該文只是一個複習思路,不瞭解訊息佇列的人建議先看《訊息佇列從入門到精通》 ##一、為什麼使用訊息佇列 三個最主要的應用場景:解耦、非同步、削峰 1、解耦 傳統模式: 缺點:系統間的耦合性太強,如上圖示,系統 A 在程式碼中直接呼叫系統 B 和

分散式 Redis 複習

引言 為什麼寫這篇文章? 博主的《分散式之訊息佇列複習精講》得到了大家的好評,內心誠惶誠恐,想著再出一篇關於複習精講的文章。但是還是要說明一下,複習精講的文章偏面試準備,真正在開發過程中,還是腳踏實地,一步一個腳印,不要投機取巧。 考慮到絕大部分寫業務的程式設計

【轉載】分散式redis複習

引言 為什麼寫這篇文章? 博主的《分散式之訊息佇列複習精講》得到了大家的好評,內心誠惶誠恐,想著再出一篇關於複習精講的文章。但是還是要說明一下,複習精講的文章偏面試準備,真正在開發過程中,還是腳踏實地,一步一個腳印,不要投機取巧。 考慮到絕大部分寫業務的程式設計師

分散式redis複習

分析:這個問題其實相當重要,到底redis有沒用到家,這個問題就可以看出來。比如你redis只能存5G資料,可是你寫了10G,那會刪5G的資料。怎麼刪的,這個問題思考過麼?還有,你的資料已經設定了過期時間,但是時間到了,記憶體佔用率還是比較高,有思考過原因麼?回答: redis採用的是定期刪除+惰性刪除策略。

分散式架構核心元件訊息佇列

訊息佇列已經逐漸成為分散式應用場景、內部通訊、以及秒殺等高併發業務場景的核心手段,它具有低耦合、可靠投遞、廣播、流量控制、最終一致性 等一系列功能。 無論是 RabbitMQ、RocketMQ、ActiveMQ、Kafka還是其它等,都有的一些基本原理、術語、機制等,總結分享出來,希望大家在使用訊息佇列

[分散式學習]訊息佇列rocketmq筆記

文件地址 RocketMQ架構 嗶哩嗶哩上的視訊 mq有很多,近期買了《分散式訊息中介軟體實踐》這本書,學習關於mq的相關知識。mq大致有有4個功能: 非同步處理。比如業務端需要給使用者傳送郵件,不需要等傳送完了之後才讓業務端的呼叫程式碼返回。 服務解耦。服務之間呼叫不需要在程式碼上寫死呼叫某某服務,只

Redis訊息佇列

SpringBoot 結合redis實現訊息佇列功能 釋出者: 配置連線工廠 @Bean public StringRedisTemplate template(RedisConnectionFactory connectionFactory){ retu

日誌系統訊息佇列的應用

kafka的概述 Kakfa是由LinkedIn公司開發的一個分散式的訊息系統,後成為Apache頂級開源專案,它使用Scala編寫,以可水平擴充套件和高吞吐率的特性而被廣泛使用。 ps: 通過上述百度百科的概述,只知其然而不知其所以然。 kafka 大家都知道是訊息佇列,那麼籠統的說訊息佇列是

Cris 玩轉大資料系列訊息佇列神器 Kafka

Cris 玩轉大資料系列之訊息佇列神器 Kafka Author:Cris 文章目錄 Cris 玩轉大資料系列之訊息佇列神器 Kafka Author:Cris 1. Kafka 概述

HTML 轉 PDF wkhtmltopdf 工具

術語定義 文件物件 “文件物件”是指PDF文件中的文件物件,共有三種類型的“文件物件”,他們分別是“頁面物件”,“封面物件”和“目錄物件”。 頁面物件 “頁面物件”是指以頁面的形式在PDF文件中呈現的物件,這個是相對於“封面物件”和“目錄物件”來講的。此類物件會成為P

Java架構訊息佇列 (一):訊息佇列的概述

訊息佇列系列分享大綱:  一、訊息佇列的概述 二、訊息佇列之RabbitMQ的使用 三、訊息佇列之Kafka的使用 四、訊息佇列之RabbitMQ的原理詳解 五、訊息佇列之Kafka的原理詳解 六、訊息佇列之面試集錦 1.訊息佇列的概述 訊息佇列(Me

視訊第13章(高併發訊息佇列思路)

1、訊息佇列 訊息佇列已經逐漸成為企業IT系統內部通訊的核心手段。它具有低耦合、可靠投遞、廣播、流量控制、最終一致性等一系列功能,成為非同步RPC的主要手段之一。 訊息被處理的過程相當於流程A被處理。我們這裡以一個實際的模型來討論下,比如使用者下單成功時給使

【Linux】Linux程序間通訊訊息佇列

1、訊息佇列概念引入    訊息佇列提供了一個從一個程序向另外一個程序傳送一塊資料的方法每個資料塊都被認為是有一個型別,接收者程序接收的資料塊可以有不同的型別值訊息佇列也有管道一樣的不足,就是每個訊息的最大長度是有上限的(MSG

Linux 學習筆記—程序通訊 訊息佇列、訊號量、共享記憶體的概念區別聯絡

2.5 訊息佇列(Message queues) 訊息佇列是核心地址空間中的內部連結串列,通過linux核心在各個程序直接傳遞內容,訊息順序地傳送到訊息佇列中,並以幾種不同的方式從佇列中獲得,每個訊息佇列可以用IPC識別符號唯一地進行識別。核心中的訊息佇列是通過

PHP高階程式設計訊息佇列

轉載:https://blog.csdn.net/luyaran/article/details/53034382 1. 什麼是訊息佇列 訊息佇列(英語:Message queue)是一種程序

mysql訊息佇列

訊息佇列:在訊息的傳輸過程中儲存訊息的容器。 訊息佇列管理器在將訊息從它的源中繼到它的目標時充當中間人。佇列的主要目的是提供路由並保證訊息的傳遞;如果傳送訊息時接收者不可用,訊息佇列會保留訊息,直到可以成功地傳遞它。 如圖所示: 在不使用訊息佇列的情況下,使用者的請求資料直接寫入資

C#基礎 --- 訊息佇列例子

本機上建立一個訊息佇列: namespace XXX.XXX.MSMQBuilder { class Program { static void Main(strin

中介軟體訊息佇列

一、簡介 訊息佇列中介軟體是分散式系統中重要的元件,主要解決應用耦合,非同步訊息,流量削鋒等問題。實現高效能、高可用、可伸縮和最終一致性架構。使用較多的訊息佇列有ActiveMQ、RabbitMQ、ZeroMQ、Kafka、MetaMQ、RocketMQ。 二、訊息佇列應