1、什么是消息隊列?
消息隊列,是分布式系統中重要的組件。
- 主要解決應用耦合,異步消息,流量削鋒等問題。
- 可實現高性能,高可用,可伸縮和最終一致性架構,是大型分布式系統不可缺少的中間件。
目前主流的消息隊列有:
- Kafka
- RabbitMQ
- RocketMQ ,老版本是 MetaQ 。
- ActiveMQ ,目前用的人越來越少了。
另外,消息隊列容易和 Java 中的本地 MessageQueue 搞混,所以消息隊列更多被稱為消息中間件、分布式消息隊列等等。
二、消息隊列由哪些角色組成?
如下圖所示:
- 生產者(Producer):負責產生消息。
- 消費者(Consumer):負責消費消息
- 消息代理(Message Broker):負責存儲消息和轉發消息兩件事情。其中,轉發消息分為推送和拉取兩種方式。
1. 拉取(Pull),是指 Consumer 主動從 Message Broker 獲取消息
2. 推送(Push),是指 Message Broker 主動將 Consumer 感興趣的消息推送給 Consumer 。
三、消息隊列有哪些使用場景?
一般來說,有下面使用場景:
- 應用解耦
- 異步處理
- 流量削峰
- 消息通訊
- 日志處理
其中,應用解耦、異步處理是比較核心的。
四、Kafka的面試題
1.Apache Kafka 是什么?
Kafka 是基於發布與訂閱的消息系統。它最初由 LinkedIn 公司開發,之后成為 Apache 項目的一部分。Kafka 是一個分布式的,可分區的,冗余備份的持久性的日志服務。它主要用於處理活躍的流式數據。
在大數據系統中,常常會碰到一個問題,整個大數據是由各個子系統組成,數據需要在各個子系統中高性能、低延遲的不停流轉。傳統的企業消息系統並不是非常適合大規模的數據處理。為了同時搞定在線應用
(消息)和離線應用(數據文件、日志),Kafka 就出現了。Kafka 可以起到兩個作用:
① 降低系統組網復雜度。
② 降低編程復雜度,各個子系統不在是相互協商接口,各個子系統類似插口插在插座上,Kafka 承擔高速數據總線的作用。
2.Kafka中的ISR、AR又代表什么?ISR的伸縮又指什么?
ISR:In-Sync Replicas 副本同步隊列
AR:Assigned Replicas 所有副本
ISR是由leader維護,follower從leader同步數據有一些延遲(包括延遲時間replica.lag.time.max.ms和延遲條數replica.lag.max.messages兩個維度, 當前最新的版本0.10.x中只支持
replica.lag.time.max.ms這個維度),任意一個超過閾值都會把follower剔除出ISR, 存入OSR(Outof-Sync Replicas)列表,新加入的follower也會先存放在OSR中。AR=ISR+OSR。
3.kafka中的broker 是干什么的?
broker 是消息的代理,Producers往Brokers里面的指定Topic中寫消息,Consumers從Brokers里面拉取指定Topic的消息,然后進行業務處理,broker在中間起到一個代理保存消息的中轉站。
4.kafka中的 zookeeper 起到什么作用,可以不用zookeeper么?
它最初由 LinkedIn 公司開發,之后成為 Apache 項目的一部分。Kafka 是一個分布式的,可分區的,冗余備份的持久性的日志服務。它主要用於處理活躍的流式數據。
在大數據系統中,常常會碰到一個問題,整個大數據是由各個子系統組成,數據需要在各個子系統中高性能、低延遲的不停流轉。傳統的企業消息系統並不是非常適合大規模的數據處理。為了同時搞定在線應用
(消息)和離線應用(數據文件、日志),Kafka 就出現了。Kafka 可以起到兩個作用:
5.kafka follower如何與leader同步數據?
Kafka的復制機制既不是完全的同步復制,也不是單純的異步復制。完全同步復制要求All Alive Follower都復制完,這條消息才會被認為commit,這種復制方式極大的影響了吞吐率。而異步復制方
式下,Follower異步的從Leader復制數據,數據只要被Leader寫入log就被認為已經commit,這種情況下,如果leader掛掉,會丟失數據,kafka使用ISR的方式很好的均衡了確保數據不丟失以及吞
吐率。Follower可以批量的從Leader復制數據,而且Leader充分利用磁盤順序讀以及send file(zero copy)機制,這樣極大的提高復制性能,內部批量寫磁盤,大幅減少了Follower與Leader的消息量差。
6.什么情況下一個 broker 會從 isr中踢出去?
leader會維護一個與其基本保持同步的Replica列表,該列表稱為ISR(in-sync Replica),每個Partition都會有一個ISR,而且是由leader動態維護 ,如果一個follower比一個leader落后太多,或者超過
一定時間未發起數據復制請求,則leader將其重ISR中移除 。
7.kafka 為什么那么快?
Cache Filesystem Cache PageCache緩存
順序寫 由於現代的操作系統提供了預讀和寫技術,磁盤的順序寫大多數情況下比隨機寫內存還要快。
Zero-copy 零拷技術減少拷貝次數
Batching of Messages 批量量處理。合並小的請求,然后以流的方式進行交互,直頂網絡上限。
Pull 拉模式 使用拉模式進行消息的獲取消費,與消費端處理能力相符。
8.kafka producer如何優化打入速度?
增加線程
提高 batch.size
增加更多 producer 實例
增加 partition 數
設置 acks=-1 時,如果延遲增大:可以增大 num.replica.fetchers(follower 同步數據的線程數)來調解;
跨數據中心的傳輸:增加 socket 緩沖區設置以及 OS tcp 緩沖區設置。
9.kafka producer 打數據,ack 為 0, 1, -1 的時候代表啥, 設置 -1 的時候,什么情況下,leader 會認為一條消息 commit了
1(默認) 數據發送到Kafka后,經過leader成功接收消息的的確認,就算是發送成功了。在這種情況下,如果leader宕機了,則會丟失數據。
0 生產者將數據發送出去就不管了,不去等待任何返回。這種情況下數據傳輸效率最高,但是數據可靠性確是最低的。
-1 producer需要等待ISR中的所有follower都確認接收到數據后才算一次發送完成,可靠性最高。當ISR中所有Replica都向Leader發送ACK時,leader才commit,這時候producer才能認為一個請求中的消息都commit了。
10.Kafka中是怎么體現消息順序性的?
kafka每個partition中的消息在寫入時都是有序的,消費時,每個partition只能被每一個group中的一個消費者消費,保證了消費時也是有序的。
整個topic不保證有序。如果為了保證topic整個有序,那么將partition調整為1.
五、RabbitMQ面試題
1、什么是RabbitMQ?為什么使用RabbitMQ?
RabbitMQ是一款開源的,Erlang編寫的,基於AMQP協議的,消息中間件;
可以用它來:解耦、異步、削峰。
2、RabbitMQ有什么優缺點?
優點:解耦、異步、削峰;
缺點:降低了系統的穩定性:本來系統運行好好的,現在你非要加入個消息隊列進去,那消息隊列掛了,你的系統不是呵呵了。因此,系統可用性會降低;
增加了系統的復雜性:加入了消息隊列,要多考慮很多方面的問題,比如:一致性問題、如何保證消息不被重復消費、如何保證消息可靠性傳輸等。因此,需要考慮的東西更多,復雜性增大。
3、如何保證RabbitMQ的高可用?
沒有哪個項目會只用一搭建一台RabbitMQ服務器提供服務,風險太大;
4、如何保證RabbitMQ不被重復消費?
先說為什么會重復消費:正常情況下,消費者在消費消息的時候,消費完畢后,會發送一個確認消息給消息隊列,消息隊列就知道該消息被消費了,就會將該消息從消息隊列中刪除;
但是因為網絡傳輸等等故障,確認信息沒有傳送到消息隊列,導致消息隊列不知道自己已經消費過該消息了,再次將消息分發給其他的消費者。
針對以上問題,一個解決思路是:保證消息的唯一性,就算是多次傳輸,不要讓消息的多次消費帶來影響;保證消息等冪性;
比如:在寫入消息隊列的數據做唯一標示,消費消息時,根據唯一標識判斷是否消費過;
5、如何保證RabbitMQ消息的可靠傳輸?
消息不可靠的情況可能是消息丟失,劫持等原因;
丟失又分為:生產者丟失消息、消息列表丟失消息、消費者丟失消息;
生產者丟失消息:從生產者弄丟數據這個角度來看,RabbitMQ提供transaction和confirm模式來確保生產者不丟消息;
transaction機制就是說:發送消息前,開啟事務(channel.txSelect()),然后發送消息,如果發送過程中出現什么異常,事務就會回滾(channel.txRollback()),如果發送成功則提交事務(channel.txCommit())。然而,這種方式有個缺點:吞吐量下降;
confirm模式用的居多:一旦channel進入confirm模式,所有在該信道上發布的消息都將會被指派一個唯一的ID(從1開始),一旦消息被投遞到所有匹配的隊列之后;
rabbitMQ就會發送一個ACK給生產者(包含消息的唯一ID),這就使得生產者知道消息已經正確到達目的隊列了;
如果rabbitMQ沒能處理該消息,則會發送一個Nack消息給你,你可以進行重試操作。
消息隊列丟數據:消息持久化。
處理消息隊列丟數據的情況,一般是開啟持久化磁盤的配置。
這個持久化配置可以和confirm機制配合使用,你可以在消息持久化磁盤后,再給生產者發送一個Ack信號。
這樣,如果消息持久化磁盤之前,rabbitMQ陣亡了,那么生產者收不到Ack信號,生產者會自動重發。
那么如何持久化呢?
這里順便說一下吧,其實也很容易,就下面兩步
- 將queue的持久化標識durable設置為true,則代表是一個持久的隊列
- 發送消息的時候將deliveryMode=2
這樣設置以后,即使rabbitMQ掛了,重啟后也能恢復數據
消費者丟失消息:消費者丟數據一般是因為采用了自動確認消息模式,改為手動確認消息即可!
消費者在收到消息之后,處理消息之前,會自動回復RabbitMQ已收到消息;
如果這時處理消息失敗,就會丟失該消息;
解決方案:處理消息成功后,手動回復確認消息。
6、如何保證RabbitMQ消息的順序性?
單線程消費保證消息的順序性;對消息進行編號,消費者處理消息是根據編號處理消息;
六、ActiveMQ
1.什么是activemq?
3.2 p2p(point-to-point)(點對點)
p2p的過程則理解起來比較簡單。它好比是兩個人打電話,這兩個人是獨享這一條通信鏈路的。一方發送消息,另外一方接收,就這么簡單。在實際應用中因為有多個用戶對使用p2p的鏈路。
- publish(發布)-subscribe(訂閱)方式的處理
- 4.2p - p(點對點)方式的處理