1.RabbitMQ如何保證消息不丟失
- 開啟生產者確認機制,確保生產者的消息能到達隊列
- 開啟持久化功能,確保消息未消費前在隊列中不會丟失(交換機,隊列,消息都需要開啟持久化功能)
- 開啟消費者確認機制為auto,由spring確認消息處理成功后完成ack
- 開啟消費者失敗重試機制(比如設置最多重試次數為3),多次重試失敗后將消息投遞到異常交換機,交由人工處理
2.說一說消息重復消費問題
- 導致消息重復的原因一般是設置了消息重試機制。但是由于網絡抖動或者消費者掛了,導致消息沒有被確認還在消息隊列中,然后重復發送導致的
- 解決這個問題最好的方法是用唯一標識去處理,消費時候去數據庫查一下,如果這個消息的唯一標識已經存在了,那么就是已經消費過了
- 其次是可以用redis分布式鎖或者數據庫鎖(樂觀鎖,悲觀鎖)去解決。
3.說一說RabbitMQ中死信交換機(RabbitMQ延遲隊列)
- 延遲隊列一般的應用場景有超時訂單、限時優惠、定時發布等
- 延遲隊列是用到了死信交換機和TTL(消息存活時間)實現的
- 消息超時未消費就會變成死信(死信的其他情況:拒絕被消費,隊列滿了)
- 死信會被放到死信交換機里面,由死信交換機綁定的隊列去消費(死信交換機在創建消息隊列的時候就需要去指定死信交換機是誰)。
- 延遲隊列插件也可以實現延遲隊列(DelayExchange),發送消息時,添加x-delay頭,值為超時時間
4.消息堆積問題如何解決
- 增加更多的消費者,提高消費速度
- 在消費者內使用線程池,提高消息處理速度
- 使用惰性隊列,把消息放在磁盤里面,獲得更高的存儲上限。但是這樣受限于磁盤IO,時效性會降低。
5.RabbmitMq怎么解決高可用
- 采用鏡像模式搭建集群,鏡像的結構是一主多從,所有操作時主節點完成,之后同步給從節點。如果主節點宕機,鏡像節點會成為新的主節點。但是如果在同步之前主節點就掛了,可能會造成數據丟失。
- 采用仲裁隊列解決鏡像集群可能出現的數據丟失問題,仲裁隊列和鏡像隊列一樣都是主從模式,主從同步基于Raft協議,強一致。且使用起來也很方便,只要聲明隊列的時候表示是仲裁隊列即可。
Raft協議: Raft是一種旨在簡化實現和理解的分布式系統共識算法。其核心在于通過選舉一個“領導者”來處理客戶端請求,并將這些請求作為日志條目復制到其他“跟隨者”節點,以確保所有節點數據的一致性。每個節點在任一時刻都處于三種狀態之一:領導者、跟隨者或候選人(用于選舉新領導者)。Raft通過任期(邏輯時鐘)和嚴格的日志復制規則保證了即使部分節點故障,系統仍能保持一致性和可用性。簡而言之,Raft使分布式系統能夠高效、可靠地達成共識,確保數據一致性。
6.Kafka如何保證消息不丟失
需要從三個層面去解決這個問題:
- 生產者發送消息到Brocker丟失
– 設置異步發送,發送失敗使用回調進行記錄或重發
– 失敗重試,參數配置,可以設置重試次數 - 消息在Brockert中存儲丟失
發送確認acks,選擇all,讓所有的副本都參與保存數據后確認,但是這樣效率最低,可以設置為1,只要集群首領收到消息,即可發送消息確認。 - 消費者從Brocker接收消息丟失
– 關閉自動提交偏移量,開啟手動提交偏移量
– 提交方式,最好是同步+異步提交
7.Kafka中消息的重復消費問題如何解決的
- 關閉自動提交偏移量,開啟手動提交偏移量
- 提交方式,最好是同步+異步提交
- 使用冪等方案
8.Kafka消費如何保證順序性
在kafka中,一個topic的數據存儲在不同的分區中,每個分區都有按照順序存儲的偏移量,這就導致如果一個消費者關聯了多個分區,分區就不能保證連續性。
解決:
- 發送消息時指定分區號,將需要順序消費的消息全部發送到同一分區
- 發送消息時,按照業務設置相同的key,核心依然是將需要順序消費的信息全部發送給同一分區,以此保證消息消費的順序性
9.Kafka高可用機制了解過嗎
Kafka高可用機制主要體現在兩個方面
集群:
一個kafka集群由多個broker3實例組成,即使某一臺宕機,也不耽誤其他broker繼續對外提供服務
復制機制:
- 一個topic有多個分區,每個分區有多個副本,有一個leader,其余的是follower,副本存儲在不同的broker中
- 所有的分區副本的內容是都是相同的,如果leader發生故障時,會自動將其中一個follower提升為leader,保證了系統的容錯性、高可用性
- 分區副本分為兩類
– 一類是ISR,需要同步保存數據的副本,leader掛掉之后,會優先從ISR選取,一般建議設置一到兩個,因為是同步復制,多了影響效率
– 一類是普通副本,異步同步數據
10.說一說Kafka的數據清理機制
需要先說明kafka存儲結構
- Kafka中topic的數據存儲在分區上,一個分區如果過大就會進行分段存儲,及一個分區下可能會存在多個文件段,一個文件段被稱為segment
- 每個文件段都對應了三個日志文件:索引文件(xxx.index)、數據文件(xxx.log)、時間索引文件(xxx.timeindex)。每段的文件名相同,后綴不同
- 分段的好處是,第一能夠減少單個文件內容的大小,查找數據方便,第二方便kafka進行日志清理。
再說明kafaka的兩個日志的清理策略
- 根據消息的保留時間,當消息保存的時間超過了指定的時間,就會觸發清理,默認是168小時(7天)
- 根據topic存儲的數據大小,當topic所占的日志文件大小大于一定的閾值,則開始刪除最久的消息。(默認關閉)
11.說一說kafka的高性能設計
- 消息分區: 不受單臺服務器的限制,可以不受限的處理更多的數據
- 順序讀寫: 磁盤順序讀寫,提升讀寫效率(文件內容是追加寫入的)
- 頁緩存: 把磁盤中的數據緩存到內存中,把對磁盤的訪問變為對內存的訪問
- 零拷貝: 減少上下文切換及數據拷貝
- 消息壓縮:減少磁盤IO和網絡O
- 分批發送:將消息打包批量發送,減少網絡開銷
零拷貝
普通拷貝:
- 從硬件中的磁盤文件到內核空間的頁緩存一次
- 從內核空間的頁緩存到用戶空間的kafka一次
- 從用戶空間的kafka到內核空間的Socket緩沖區一次
- 從內核空間的Socket緩沖區到硬件中的網卡一次
共進行了四次拷貝
零拷貝:
- 從硬件中的磁盤文件到內核空間的頁緩存一次
- 從內核空間的頁緩存到硬件中的網卡一次
共進行了兩次拷貝