中介軟體相關問題整理

張彥峰ZYF發表於2020-04-07

目錄

1.用過哪些MQ,怎麼用的,和其他mq比較有什麼優缺點,MQ的連線是執行緒安全的嗎?

一、常見的訊息中介軟體

1.Kafka主要特性、優缺點

2.RabbitMQ主要特性、優缺點

3.RocketMQ主要特性、優缺點

4.ActiveMQ主要特性、優缺點

二、訊息中介軟體相關知識

1.訊息中介軟體的組成

2.訊息中介軟體模式分類

點對點

3.訊息中介軟體的普遍優勢

4.訊息中介軟體常用協議

三、訊息佇列應用場景

場景一:非同步處理

場景二:應用解耦

場景三:流量削鋒(一般在秒殺或團搶活動中使用廣泛)

場景四:日誌處理

場景五:訊息通訊

2.MQ系統的資料如何保證不丟失?

一、MQ原則

二、丟失資料場景分析

(一)rabbitmq丟失資料場景分析

1.生產者弄丟了資料

2.rabbitmq自己丟了資料

3.消費端弄丟了資料

(二)kafka丟失資料場景分析

三、如何防止訊息丟失

(一)rabbitmq防止訊息丟失

1.生產者丟失訊息

2.rabbitmq自己弄丟了資料

3.消費者弄丟了資料

(二)kafka防止訊息丟失

1.消費端弄丟了資料

2.kafka弄丟了資料

3.生產者弄丟了資料

補充問題:

關於MQ的幾件小事(五)如何保證訊息按順序執行

關於MQ的幾件小事(三)如何保證訊息不重複消費

關於MQ的幾件小事(二)如何保證訊息佇列的高可用

Kafka的檔案儲存機制

Kafka 如何保證可靠性

Kafka訊息是採用Pull模式,還是Push模式

Kafka是如何實現高吞吐率的

Kafka判斷一個節點還活著的兩個條件

參考書籍、文獻和資料


備註:針對基本問題做一些基本的總結,不是詳細解答!

1.用過哪些MQ,怎麼用的,和其他mq比較有什麼優缺點,MQ的連線是執行緒安全的嗎?

一、常見的訊息中介軟體

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

當前使用較多的訊息佇列有RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ、MetaMQ等,而部分資料庫如Redis、MySQL以及phxsql也可實現訊息佇列的功能

1.Kafka主要特性、優缺點

Apache Kafka是一個分散式訊息釋出訂閱系統。Kafka效能高效、可擴充套件良好並且可持久化。它的分割槽特性、可複製和可容錯都是其不錯的特性。

主要特性

  • 快速持久化:可以在O(1)的系統開銷下進行訊息持久化
  • 高吞吐:在一臺普通的伺服器上既可以達到10W/s的吞吐速率;
  • 完全的分散式系統:Broker、Producer和Consumer都原生自動支援分散式,自動實現負載均衡
  • 支援同步和非同步複製兩種高可用機制;
  • 支援資料批量傳送和拉取
  • 零拷貝技術(zero-copy):減少IO操作步驟,提高系統吞吐量
  • 資料遷移、擴容對使用者透明;
  • 無需停機即可擴充套件機器;
  • 其他特性:豐富的訊息拉取模型、高效訂閱者水平擴充套件、實時的訊息訂閱、億級的訊息堆積能力、定期刪除機制

優點

  • 客戶端語言豐富:支援Java、.Net、PHP、Ruby、Python、Go等多種語言
  • 高效能:單機寫入TPS約在100萬條/秒,訊息大小10個位元組;
  • 提供完全分散式架構,並有replica機制,擁有較高的可用性和可靠性,理論上支援訊息無限堆積
  • 支援批量操作
  • 消費者採用Pull方式獲取訊息。訊息有序,通過控制能夠保證所有訊息被消費且僅被消費一次;
  • 有優秀的第三方KafkaWeb管理介面Kafka-Manager
  • 在日誌領域比較成熟,被多家公司和多個開源專案使用

缺點

  • Kafka單機超過64個佇列/分割槽時,Load時會發生明顯的飆高現象。佇列越多,負載越高,傳送訊息響應時間變長;
  • 使用短輪詢方式,實時性取決於輪詢間隔時間;
  • 消費失敗不支援重試
  • 支援訊息順序,但是一臺代理當機後,就會產生訊息亂序
  • 社群更新較慢。

2.RabbitMQ主要特性、優缺點

RabbitMQ於2007年釋出,是一個在AMQP(高階訊息佇列協議)基礎上完成的,可複用的企業訊息系統,是當前最主流的訊息中介軟體之一。

主要特性

  • 可靠性:提供了多種技術可以讓你在效能和可靠性之間進行權衡。這些技術包括永續性機制、投遞確認、釋出者證實和高可用性機制;
  • 靈活的路由:訊息在到達佇列前是通過交換機進行路由的。RabbitMQ為典型的路由邏輯提供了多種內建交換機型別。如果你有更復雜的路由需求,可以將這些交換機組合起來使用,你甚至可以實現自己的交換機型別,並且當做RabbitMQ的外掛來使用;
  • 訊息叢集:在相同區域網中的多個RabbitMQ伺服器可以聚合在一起,作為一個獨立的邏輯代理來使用;
  • 佇列高可用:佇列可以在叢集中的機器上進行映象,以確保在硬體問題下還保證訊息安全;
  • 支援多種協議:支援多種訊息佇列協議;
  • 支援多種語言:用Erlang語言編寫,支援只要是你能想到的所有程式語言;
  • 管理介面:RabbitMQ有一個易用的使用者介面,使得使用者可以監控和管理訊息Broker的許多方面;
  • 跟蹤機制:如果訊息異常,RabbitMQ 提供訊息跟蹤機制,使用者可以找出發生了什麼;
  • 外掛機制:提供了許多外掛,來從多方面進行擴充套件,也可以編寫自己的外掛。

優點

  • 由於Erlang語言的特性,訊息佇列效能較好,支援高併發;
  • 健壯、穩定、易用、跨平臺、支援多種語言、文件齊全;
  • 有訊息確認機制和持久化機制,可靠性高;
  • 高度可定製的路由;
  • 管理介面較豐富,在網際網路公司也有較大規模的應用,社群活躍度高。

缺點

  • 儘管結合 Erlang 語言本身的併發優勢,效能較好,但是不利於做二次開發和維護
  • 實現了代理架構,意味著訊息在傳送到客戶端之前可以在中央節點上排隊。此特性使得RabbitMQ易於使用和部署,但是使得其執行速度較慢,因為中央節點增加了延遲,訊息封裝後也比較大;需要學習比較複雜的介面和協議,學習和維護成本較高。

3.RocketMQ主要特性、優缺點

RocketMQ出自阿里的開源產品,用Java語言實現,在設計時參考了Kafka,並做出了自己的一些改進,訊息可靠性上比Kafka更好。RocketMQ在阿里內部被廣泛應用在訂單,交易,充值,流計算,訊息推送,日誌流式處理,binglog分發等場景。

主要特性

  • 基於佇列模型:具有高效能、高可靠、高實時、分散式等特點
  • Producer、Consumer、佇列都支援分散式
  • Producer向一些佇列輪流傳送訊息,佇列集合稱為TopicConsumer如果做廣播消費,則一個Consumer例項消費這個Topic對應的所有佇列如果做叢集消費,則多個Consumer 例項平均消費這個Topic對應的佇列集合
  • 能夠保證嚴格的訊息順序
  • 提供豐富的訊息拉取模式
  • 高效的訂閱者水平擴充套件能力
  • 實時的訊息訂閱機制
  • 億級訊息堆積能力
  • 較少的外部依賴。

優點

  • 單機支援1萬以上持久化佇列
  • RocketMQ的所有訊息都是持久化的,先寫入系統PAGECACHE,然後刷盤,可以保證記憶體與磁碟都有一份資料,而訪問時,直接從記憶體讀取;
  • 模型簡單,介面易用(JMS的介面很多場合並不太實用);
  • 效能非常好,可以允許大量堆積訊息在Broker中
  • 支援多種消費模式,包括叢集消費、廣播消費等
  • 各個環節分散式擴充套件設計,支援主從和高可用
  • 開發度較活躍,版本更新很快

缺點

  • 支援的客戶端語言不多,目前是Java及C++,其中C++還不成熟;
  • RocketMQ社群關注度及成熟度也不及前兩者
  • 沒有Web管理介面,提供了一個 CLI (命令列介面) 管理工具帶來查詢、管理和診斷各種問題
  • 沒有在MQ核心裡實現JMS等介面

4.ActiveMQ主要特性、優缺點

ActiveMQ是由Apache出品,ActiveMQ是一個完全支援JMS1.1和J2EE 1.4規範的JMS Provider實現。它非常快速,支援多種語言的客戶端和協議,而且可以非常容易的嵌入到企業的應用環境中,並有許多高階功能。

主要特性

  • 服從JMS規範:JMS 規範提供了良好的標準和保證,包括:同步 或 非同步 的訊息分發,一次和僅一次的訊息分發,訊息接收和訂閱等等。遵從JMS規範的好處在於,不論使用什麼JMS實現提供者,這些基礎特性都是可用的;
  • 連線靈活性:ActiveMQ提供了廣泛的連線協議,支援的協議有:HTTP/S,IP多播,SSL,TCP,UDP等等。對眾多協議的支援讓ActiveMQ擁有了很好的靈活性;
  • 支援的協議種類多:OpenWire、STOMP、REST、XMPP、AMQP;
  • 持久化外掛和安全外掛:ActiveMQ提供了多種持久化選擇。而且,ActiveMQ的安全性也可以完全依據使用者需求進行自定義鑑權和授權;
  • 支援的客戶端語言種類多:除了Java之外,還有:C/C++,.NET,Perl,PHP,Python,Ruby;
  • 代理叢集:多個ActiveMQ代理可以組成一個叢集來提供服務;
  • 異常簡單的管理:ActiveMQ是以開發者思維被設計的。所以,它並不需要專門的管理員,因為它提供了簡單又使用的管理特性。有很多中方法可以監控ActiveMQ不同層面的資料,包括使用在JConsole或者在ActiveMQ的WebConsole中使用JMX。通過處理JMX的告警訊息,通過使用命令列指令碼,甚至可以通過監控各種型別的日誌。

優點

  • 跨平臺(JAVA編寫與平臺無關,ActiveMQ幾乎可以執行在任何的JVM上)
  • 可以用JDBC可以將資料持久化到資料庫。雖然使用JDBC會降低ActiveMQ的效能,但是資料庫一直都是開發人員最熟悉的儲存介質;
  • 支援JMS規範:支援JMS規範提供的統一介面;
  • 支援自動重連和錯誤重試機制
  • 有安全機制:支援基於shiro,jaas等多種安全配置機制,可以對Queue/Topic進行認證和授權;
  • 監控完善:擁有完善的監控,包括WebConsole,JMX,Shell命令列,Jolokia的RESTful API;
  • 介面友善:提供的WebConsole可以滿足大部分情況,還有很多第三方的元件可以使用,比如hawtio

缺點

  • 社群活躍度不及RabbitMQ高
  • 根據其他使用者反饋,會出莫名其妙的問題,會丟失訊息
  • 目前重心放到activemq6.0產品Apollo,對5.x的維護較少;
  • 不適合用於上千個佇列的應用場景

二、訊息中介軟體相關知識

1.訊息中介軟體的組成

  • Broker:訊息伺服器,作為server提供訊息核心服務
  • Producer:訊息生產者,業務的發起方,負責生產訊息傳輸給broker
  • Consumer:訊息消費者,業務的處理方,負責從broker獲取訊息並進行業務邏輯處理
  • Topic:主題,釋出訂閱模式下的訊息統一彙集地,不同生產者向topic傳送訊息,由MQ伺服器分發到不同的訂閱者,實現訊息的廣播
  • Queue:佇列,PTP模式下,特定生產者向特定queue傳送訊息,消費者訂閱特定的queue完成指定訊息的接收
  • Message:訊息體,根據不同通訊協議定義的固定格式進行編碼的資料包,來封裝業務資料,實現訊息的傳輸

2.訊息中介軟體模式分類

  • 點對點

PTP點對點:使用queue作為通訊載體 

訊息生產者生產訊息傳送到queue中,然後訊息消費者從queue中取出並且消費訊息。 
訊息被消費以後,queue中不再儲存,所以訊息消費者不可能消費到已經被消費的訊息。 Queue支援存在多個消費者,但是對一個訊息而言,只會有一個消費者可以消費

  • 釋出/訂閱

Pub/Sub釋出訂閱(廣播):使用topic作為通訊載體 

訊息生產者(釋出)將訊息釋出到topic中,同時有多個訊息消費者(訂閱)消費該訊息。和點對點方式不同,釋出到topic的訊息會被所有訂閱者消費。

queue實現了負載均衡,將producer生產的訊息傳送到訊息佇列中,由多個消費者消費。但一個訊息只能被一個消費者接受,當沒有消費者可用時,這個訊息會被儲存直到有一個可用的消費者。 
topic實現了釋出和訂閱,當你釋出一個訊息,所有訂閱這個topic的服務都能得到這個訊息,所以從1到N個訂閱者都能得到一個訊息的拷貝

3.訊息中介軟體的普遍優勢

  • 系統解耦

互動系統之間沒有直接的呼叫關係,只是通過訊息傳輸,故系統侵入性不強,耦合度低

  • 提高系統響應時間

例如原來的一套邏輯,完成支付可能涉及先修改訂單狀態、計算會員積分、通知物流配送幾個邏輯才能完成通過MQ架構設計,就可將緊急重要(需要立刻響應)的業務放到該呼叫方法中,響應要求不高的使用訊息佇列,放到MQ佇列中,供消費者處理

  • 為大資料處理架構提供服務

通過訊息作為整合,大資料的背景下,訊息佇列還與實時處理架構整合,為資料處理提供效能支援

  • Java訊息服務——JMS

Java訊息服務(Java Message Service,JMS)應用程式介面是一個Java平臺中關於面向訊息中介軟體(MOM)的API用於在兩個應用程式之間,或分散式系統中傳送訊息,進行非同步通訊。 
JMS中的P2P和Pub/Sub訊息模式:點對點(point to point, queue)與釋出訂閱(publish/subscribe,topic)最初是由JMS定義的。這兩種模式主要區別或解決的問題就是傳送到佇列的訊息能否重複消費(多訂閱)。

4.訊息中介軟體常用協議

  • AMQP協議

AMQP即Advanced Message Queuing Protocol,一個提供統一訊息服務的應用層標準高階訊息佇列協議,是應用層協議的一個開放標準,為面向訊息的中介軟體設計。基於此協議的客戶端與訊息中介軟體可傳遞訊息,並不受客戶端/中介軟體不同產品,不同開發語言等條件的限制。 
優點:可靠、通用

  • MQTT協議

MQTT(Message Queuing Telemetry Transport,訊息佇列遙測傳輸)是IBM開發的一個即時通訊協議,有可能成為物聯網的重要組成部分。該協議支援所有平臺,幾乎可以把所有聯網物品和外部連線起來,被用來當做感測器和致動器(比如通過Twitter讓房屋聯網)的通訊協議。 
優點:格式簡潔、佔用頻寬小、移動端通訊、PUSH、嵌入式系統

  • STOMP協議

STOMP(Streaming Text Orientated Message Protocol)是流文字定向訊息協議,是一種為MOM(Message Oriented Middleware,面向訊息的中介軟體)設計的簡單文字協議。STOMP提供一個可互操作的連線格式,允許客戶端與任意STOMP訊息代理(Broker)進行互動。 
優點:命令模式(非topic\queue模式)

  • XMPP協議

XMPP(可擴充套件訊息處理現場協議,Extensible Messaging and Presence Protocol)是基於可擴充套件標記語言(XML)的協議,多用於即時訊息(IM)以及線上現場探測。適用於伺服器之間的準即時操作。核心是基於XML流傳輸,這個協議可能最終允許因特網使用者向因特網上的其他任何人傳送即時訊息,即使其作業系統和瀏覽器不同。 
優點:通用公開、相容性強、可擴充套件、安全性高,但XML編碼格式佔用頻寬大

三、訊息佇列應用場景

在實際應用中常用的使用場景:非同步處理、應用解耦、流量削鋒和訊息通訊四個場景

場景一:非同步處理

場景說明:使用者註冊後,需要發註冊郵件和註冊簡訊傳統的做法有兩種 1.序列的方式;2.並行方式

  • 序列方式:將註冊資訊寫入資料庫成功後,傳送註冊郵件,再傳送註冊簡訊。以上三個任務全部完成後,返回給客戶端。
  • 並行方式:將註冊資訊寫入資料庫成功後,傳送註冊郵件的同時,傳送註冊簡訊。以上三個任務完成後,返回給客戶端。與序列的差別是,並行的方式可以提高處理的時間。

假設三個業務節點每個使用50毫秒鐘,不考慮網路等其他開銷,則序列方式的時間是150毫秒,並行的時間可能是100毫秒。

因為CPU在單位時間內處理的請求數是一定的,假設CPU1秒內吞吐量是100次。則序列方式1秒內CPU可處理的請求量是7次(1000/150),並行方式處理的請求量是10次(1000/100)

小結:如以上案例描述,傳統的方式系統的效能(併發量,吞吐量,響應時間)會有瓶頸。如何解決這個問題呢?

引入訊息佇列,將不是必須的業務邏輯,非同步處理。改造後的架構如下:

按照以上約定,使用者的響應時間相當於是註冊資訊寫入資料庫的時間,也就是50毫秒。註冊郵件,傳送簡訊寫入訊息佇列後,直接返回,因此寫入訊息佇列的速度很快,基本可以忽略,因此使用者的響應時間可能是50毫秒。因此架構改變後,系統的吞吐量提高到每秒20 QPS。比序列提高了3倍,比並行提高了兩倍。

場景二:應用解耦

場景說明:使用者下單後,訂單系統需要通知庫存系統傳統的做法是,訂單系統呼叫庫存系統的介面。假如庫存系統無法訪問,則訂單減庫存將失敗,從而導致訂單失敗,缺點在於訂單系統與庫存系統耦合

如何解決以上問題呢?引入應用訊息佇列後的方案,如下圖:

  • 訂單系統:使用者下單後,訂單系統完成持久化處理,將訊息寫入訊息佇列,返回使用者訂單下單成功
  • 庫存系統:訂閱下單的訊息,採用拉/推的方式,獲取下單資訊,庫存系統根據下單資訊,進行庫存操作

假如:在下單時庫存系統不能正常使用,也不影響正常下單,因為下單後,訂單系統寫入訊息佇列就不再關心其他的後續操作了。實現訂單系統與庫存系統的應用解耦

場景三:流量削鋒(一般在秒殺或團搶活動中使用廣泛)

應用場景:秒殺活動,一般會因為流量過大,導致流量暴增,應用掛掉。為解決這個問題,一般需要在應用前端加入訊息佇列:可以控制活動的人數、可以緩解短時間內高流量壓垮應用。使用者的請求,伺服器接收後,首先寫入訊息佇列。假如訊息佇列長度超過最大數量,則直接拋棄使用者請求或跳轉到錯誤頁面秒殺業務根據訊息佇列中的請求資訊,再做後續處理。

場景四:日誌處理

日誌處理是指將訊息佇列用在日誌處理中,比如Kafka的應用,解決大量日誌傳輸的問題。架構簡化如下,

  • 日誌採集客戶端:負責日誌資料採集,定時寫受寫入Kafka佇列
  • Kafka訊息佇列:負責日誌資料的接收,儲存和轉發
  • 日誌處理應用:訂閱並消費kafka佇列中的日誌資料

檢視新浪kafka日誌處理應用案例:轉自(http://cloud.51cto.com/art/201507/484338.htm)

  • (1)Kafka:接收使用者日誌的訊息佇列
  • (2)Logstash:做日誌解析,統一成JSON輸出給Elasticsearch
  • (3)Elasticsearch:實時日誌分析服務的核心技術,一個schemaless,實時的資料儲存服務,通過index組織資料,兼具強大的搜尋和統計功能
  • (4)Kibana:基於Elasticsearch的資料視覺化元件,超強的資料視覺化能力是眾多公司選擇ELK stack的重要原因

場景五:訊息通訊

訊息通訊是指,訊息佇列一般都內建了高效的通訊機制,因此也可以用在純的訊息通訊。比如實現點對點訊息佇列,或者聊天室等

  • 點對點通訊:客戶端A和客戶端B使用同一佇列,進行訊息通訊。

  • 聊天室通訊:客戶端A,客戶端B,客戶端N訂閱同一主題,進行訊息釋出和接收。實現類似聊天室效果。 

以上實際是訊息佇列的兩種訊息模式,點對點或釋出訂閱模式。模型為示意圖,供參考。

2.MQ系統的資料如何保證不丟失?

一、MQ原則

資料不能多,也不能少,不能多是說訊息不能重複消費。不能少,就是說不能丟失資料。如果mq傳遞的是非常核心的訊息,支撐核心的業務,那麼這種場景是一定不能丟失資料的。

二、丟失資料場景分析

丟資料一般分為兩種,一種是mq把訊息丟了,一種就是消費時將訊息丟了。

下面從rabbitmq和kafka分別說一下,丟失資料的場景:

(一)rabbitmq丟失資料場景分析

1.生產者弄丟了資料

生產者將資料傳送到rabbitmq的時候,可能在傳輸過程中因為網路等問題而將資料弄丟了

2.rabbitmq自己丟了資料

如果沒有開啟rabbitmq的持久化,那麼rabbitmq一旦重啟,那麼資料就丟了。所以必須開啟持久化將訊息持久化到磁碟,這樣就算rabbitmq掛了,恢復之後會自動讀取之前儲存的資料,一般資料不會丟失。除非極其罕見的情況,rabbitmq還沒來得及持久化自己就掛了,這樣可能導致一部分資料丟失。

3.消費端弄丟了資料

主要是因為消費者消費時,剛消費到,還沒有處理,結果消費者就掛了,這樣你重啟之後,rabbitmq就認為你已經消費過了,然後就丟了資料。

(二)kafka丟失資料場景分析

1.生產者弄丟了資料

生產者沒有設定相應的策略,傳送過程中丟失資料

2.kafka弄丟了資料

比較常見的一個場景,就是kafka的某個broker當機了,然後重新選舉partition的leader時。如果此時follower還沒來得及同步資料,leader就掛了,然後某個follower成為了leader,他就少了一部分資料。

3.消費者弄丟了資料

消費者消費到了這個資料,然後消費之自動提交了offset,讓kafka知道你已經消費了這個訊息,當你準備處理這個訊息時,自己掛掉了,那麼這條訊息就丟了

三、如何防止訊息丟失

(一)rabbitmq防止訊息丟失

1.生產者丟失訊息

  • 可以選擇使用rabbitmq提供是事物功能

就是生產者在傳送資料之前開啟事物,然後傳送訊息,如果訊息沒有成功被rabbitmq接收到,那麼生產者會受到異常報錯,這時就可以回滾事物,然後嘗試重新傳送;如果收到了訊息,那麼就可以提交事物。

  channel.txSelect();//開啟事物
  try{
      //傳送訊息
  }catch(Exection e){
      channel.txRollback();//回滾事物
      //重新提交
  }

缺點:rabbitmq事物已開啟,就會變為同步阻塞操作,生產者會阻塞等待是否傳送成功,太耗效能會造成吞吐量的下降

  • 可以開啟confirm模式。

在生產者哪裡設定開啟了confirm模式之後,每次寫的訊息都會分配一個唯一的id,然後如何寫入了rabbitmq之中,rabbitmq會給你回傳一個ack訊息,告訴你這個訊息傳送OK了;如果rabbitmq沒能處理這個訊息,會回撥你一個nack介面,告訴你這個訊息失敗了,你可以進行重試。而且你可以結合這個機制知道自己在記憶體裡維護每個訊息的id,如果超過一定時間還沒接收到這個訊息的回撥,那麼你可以進行重發。

    //開啟confirm
    channel.confirm();
    //傳送成功回撥
    public void ack(String messageId){
      
    }

    // 傳送失敗回撥
    public void nack(String messageId){
        //重發該訊息
    }
  • 二者不同

事務機制是同步的,你提交了一個事物之後會阻塞住,但是confirm機制是非同步的,傳送訊息之後可以接著傳送下一個訊息,然後rabbitmq會回撥告知成功與否。
一般在生產者這塊避免丟失,都是用confirm機制。

2.rabbitmq自己弄丟了資料

設定訊息持久化到磁碟。設定持久化有兩個步驟:

  • ①建立queue的時候將其設定為持久化的,這樣就可以保證rabbitmq持久化queue的後設資料,但是不會持久化queue裡面的資料。
  • ②傳送訊息的時候講訊息的deliveryMode設定為2,這樣訊息就會被設為持久化方式,此時rabbitmq就會將訊息持久化到磁碟上。
  • 必須要同時開啟這兩個才可以。

而且持久化可以跟生產的confirm機制配合起來,只有訊息持久化到了磁碟之後,才會通知生產者ack,這樣就算是在持久化之前rabbitmq掛了,資料丟了,生產者收不到ack回撥也會進行訊息重發。

3.消費者弄丟了資料

使用rabbitmq提供的ack機制,首先關閉rabbitmq的自動ack,然後每次在確保處理完這個訊息之後,在程式碼裡手動呼叫ack。這樣就可以避免訊息還沒有處理完就ack。

(二)kafka防止訊息丟失

1.消費端弄丟了資料

關閉自動提交offset,在自己處理完畢之後手動提交offset,這樣就不會丟失資料

2.kafka弄丟了資料

一般要求設定4個引數來保證訊息不丟失

  • 給topic設定 replication.factor引數:這個值必須大於1,表示要求每個partition必須至少有2個副本。
  • 在kafka服務端設定min.isync.replicas引數:這個值必須大於1,表示 要求一個leader至少感知到有至少一個follower在跟自己保持聯絡正常同步資料,這樣才能保證leader掛了之後還有一個follower。
  • 在生產者端設定acks=all:表示 要求每條每條資料,必須是寫入所有replica副本之後,才能認為是寫入成功了
  • 在生產者端設定retries=MAX(很大的一個值,表示無限重試):表示 這個是要求一旦寫入事變,就無限重試

3.生產者弄丟了資料

如果按照上面設定了ack=all,則一定不會丟失資料,要求是,你的leader接收到訊息,所有的follower都同步到了訊息之後,才認為本次寫成功了如果沒滿足這個條件,生產者會自動不斷的重試,重試無限次

補充問題:

關於MQ的幾件小事(五)如何保證訊息按順序執行

https://www.jianshu.com/p/02fdcb9e8784

關於MQ的幾件小事(三)如何保證訊息不重複消費

https://www.jianshu.com/p/172295e2e978

關於MQ的幾件小事(二)如何保證訊息佇列的高可用

https://www.jianshu.com/p/ab64681beb17

Kafka的檔案儲存機制

Kafka中訊息是以topic進行分類的,生產者通過topic向Kafka broker傳送訊息,消費者通過topic讀取資料。

然而topic在物理層面又能以partition為分組,一個topic可以分成若干個partition。partition還可以細分為segment,一個partition物理上由多個segment組成,segment檔案由兩部分組成,分別為“.index”檔案和“.log”檔案,分別表示為segment索引檔案和資料檔案。這兩個檔案的命令規則為:partition全域性的第一個segment從0開始,後續每個segment檔名為上一個segment檔案最後一條訊息的offset值

Kafka 如何保證可靠性

如果我們要往 Kafka 對應的主題傳送訊息,我們需要通過 Producer 完成。前面我們講過 Kafka 主題對應了多個分割槽,每個分割槽下面又對應了多個副本;為了讓使用者設定資料可靠性, Kafka 在 Producer 裡面提供了訊息確認機制。也就是說我們可以通過配置來決定訊息傳送到對應分割槽的幾個副本才算訊息傳送成功。可以在定義 Producer 時通過 acks 引數指定。這個引數支援以下三種值:

  • acks = 0:意味著如果生產者能夠通過網路把訊息傳送出去,那麼就認為訊息已成功寫入 Kafka 。在這種情況下還是有可能發生錯誤,比如傳送的物件無能被序列化或者網路卡發生故障,但如果是分割槽離線或整個叢集長時間不可用,那就不會收到任何錯誤。在 acks=0 模式下的執行速度是非常快的(這就是為什麼很多基準測試都是基於這個模式),你可以得到驚人的吞吐量和頻寬利用率,不過如果選擇了這種模式, 一定會丟失一些訊息。
  • acks = 1:意味若 Leader 在收到訊息並把它寫入到分割槽資料檔案(不一定同步到磁碟上)時會返回確認或錯誤響應。在這個模式下,如果發生正常的 Leader 選舉,生產者會在選舉時收到一個 LeaderNotAvailableException 異常,如果生產者能恰當地處理這個錯誤,它會重試傳送悄息,最終訊息會安全到達新的 Leader 那裡。不過在這個模式下仍然有可能丟失資料,比如訊息已經成功寫入 Leader,但在訊息被複制到 follower 副本之前 Leader發生崩潰。
  • acks = all(這個和 request.required.acks = -1 含義一樣):意味著 Leader 在返回確認或錯誤響應之前,會等待所有同步副本都收到悄息。如果和min.insync.replicas 引數結合起來,就可以決定在返回確認前至少有多少個副本能夠收到悄息,生產者會一直重試直到訊息被成功提交。不過這也是最慢的做法,因為生產者在繼續傳送其他訊息之前需要等待所有副本都收到當前的訊息。

Kafka訊息是採用Pull模式,還是Push模式

Kafka最初考慮的問題是,customer應該從brokes拉取訊息還是brokers將訊息推送到consumer,也就是pull還push。在這方面,Kafka遵循了一種大部分訊息系統共同的傳統的設計:producer將訊息推送到broker,consumer從broker拉取訊息。

push模式下,當broker推送的速率遠大於consumer消費的速率時,consumer恐怕就要崩潰了。

最終Kafka還是選取了傳統的pull模式。Pull模式的另外一個好處是consumer可以自主決定是否批量的從broker拉取資料。Pull有個缺點是,如果broker沒有可供消費的訊息,將導致consumer不斷在迴圈中輪詢,直到新訊息到t達。為了避免這點,Kafka有個引數可以讓consumer阻塞知道新訊息到達。

Kafka是如何實現高吞吐率的

  1. 順序讀寫:kafka的訊息是不斷追加到檔案中的,這個特性使kafka可以充分利用磁碟的順序讀寫效能
  2. 零拷貝跳過“使用者緩衝區”的拷貝,建立一個磁碟空間和記憶體的直接對映,資料不再複製到“使用者態緩衝區”
  3. 檔案分段:kafka的佇列topic被分為了多個區partition,每個partition又分為多個段segment,所以一個佇列中的訊息實際上是儲存在N多個片段檔案中
  4. 批量傳送:Kafka允許進行批量傳送訊息,先將訊息快取在記憶體中,然後一次請求批量傳送出去
  5. 資料壓縮:Kafka還支援對訊息集合進行壓縮,Producer可以通過GZIP或Snappy格式對訊息集合進行壓縮

Kafka判斷一個節點還活著的兩個條件

  1. 節點必須可以維護和 ZooKeeper 的連線,Zookeeper 通過心跳機制檢查每個節點的連線
  2. 如果節點是個 follower,他必須能及時的同步 leader 的寫操作,延時不能太久

 

參考書籍、文獻和資料

1.https://www.cnblogs.com/Vito-Yan/p/10319826.html

2.https://blog.csdn.net/wqc19920906/article/details/82193316

3.https://www.jianshu.com/p/70c5b8d51c75

4.http://cloud.51cto.com/art/201507/484338.htm

5.https://www.jianshu.com/p/8ed16edc73e4

 

 

相關文章