wordpress 遷站網(wǎng)站外鏈發(fā)布平臺(tái)
為什么要使用消息隊(duì)列?
使用消息隊(duì)列的主要目的主要記住這幾個(gè)關(guān)鍵詞:解耦、異步、削峰填谷。
解耦: 在一個(gè)復(fù)雜的系統(tǒng)中,不同的模塊或服務(wù)之間可能需要相互依賴,如果直接使用函數(shù)調(diào)用或者 API 調(diào)用的方式,會(huì)造成模塊之間的耦合,當(dāng)其中一個(gè)模塊發(fā)生改變時(shí),需要同時(shí)修改調(diào)用方和被調(diào)用方的代碼。而使用消息隊(duì)列作為中間件,不同的模塊可以將消息發(fā)送到消息隊(duì)列中,不需要知道具體的接收方是誰,接收方可以獨(dú)立地消費(fèi)消息,實(shí)現(xiàn)了模塊之間的解耦。
異步: 有些操作比較耗時(shí),例如發(fā)送郵件、生成報(bào)表等,如果使用同步的方式處理,會(huì)阻塞主線程或者進(jìn)程,導(dǎo)致系統(tǒng)的性能下降。而使用消息隊(duì)列,可以將這些操作封裝成消息,放入消息隊(duì)列中,異步地處理這些操作,不影響主流程的執(zhí)行,提高了系統(tǒng)的性能和響應(yīng)速度。
削峰填谷:削峰填谷是一種在高并發(fā)場(chǎng)景下平衡系統(tǒng)壓力的技術(shù),通常用于平衡系統(tǒng)在高峰期和低谷期的資源利用率,提高系統(tǒng)的吞吐量和響應(yīng)速度。在削峰填谷的過程中,通常使用消息隊(duì)列作為緩沖區(qū),將請(qǐng)求放入消息隊(duì)列中,然后在系統(tǒng)負(fù)載低的時(shí)候進(jìn)行處理。這種方式可以將系統(tǒng)的峰值壓力分散到較長的時(shí)間段內(nèi),減少瞬時(shí)壓力對(duì)系統(tǒng)的影響,從而提高系統(tǒng)的穩(wěn)定性和可靠性。
另外消息隊(duì)列還有以下優(yōu)點(diǎn):
1**.可靠性高:**消息隊(duì)列通常具有高可靠性,可以實(shí)現(xiàn)消息的持久化存儲(chǔ)、消息的備份和故障恢復(fù)等功能,保證消息不會(huì)丟失。
2.**擴(kuò)展性好:**通過增加消息隊(duì)列實(shí)例或者添加消費(fèi)者實(shí)例,可以實(shí)現(xiàn)消息隊(duì)列的水平擴(kuò)展,提高系統(tǒng)的處理能力。
**3.靈活性高:**消息隊(duì)列通常支持多種消息傳遞模式,如點(diǎn)對(duì)點(diǎn)模式和發(fā)布/訂閱模式,可以根據(jù)不同的業(yè)務(wù)場(chǎng)景選擇不同的模式。
擴(kuò)展知識(shí)
消息隊(duì)列實(shí)現(xiàn)
市面上有很多成熟的消息隊(duì)列中間件可以供我們使用,其中比較常用的有kafka、activeMQ、RabbitMQ和RocketMQ等。
Kafka、ActiveMQ、RabbitMQ和RocketMQ都有哪些區(qū)別?
典型回答
Kafka、ActiveMO、RabbitMQ和RocketMQ都是常見的消息中間件,它們都提供了高性能、高可用、可擴(kuò)展的消息傳遞機(jī)制,但它們之間也有以下一些區(qū)別:
1.消息傳遞模型:Kafka主要支持發(fā)布-訂閱模型,ActiveMQ、RabbitMQ和RocketMQ則同時(shí)支持點(diǎn)對(duì)點(diǎn)和發(fā)布-訂閱兩種模型。
2.性能和吞吐量:Kafka在數(shù)據(jù)處理和數(shù)據(jù)分發(fā)方面表現(xiàn)出色,可以處理每秒數(shù)百萬條消息,而ActiveMQ、RabbitMQ和RocketMQ的吞吐量相對(duì)較低。
3.消息分區(qū)和負(fù)載均衡:Kafka將消息劃分為多個(gè)分區(qū),并分布在多個(gè)服務(wù)器上,實(shí)現(xiàn)負(fù)載均衡和高可用性。ActiveMQ、RabbitMQ和RocketMQ也支持消息分區(qū)和負(fù)載均衡,但實(shí)現(xiàn)方式不同,例如RabbitMQ使用了一種叫做Sharding的機(jī)制。
4.開發(fā)和部署復(fù)雜度:Kafka相對(duì)比較簡(jiǎn)單,易于使用和部署,但在實(shí)現(xiàn)一些高級(jí)功能時(shí)需要進(jìn)行一些復(fù)雜的配置。ActiveMQ、RabbitMQ和RocketMQ則提供了更多的功能和選項(xiàng),也更加靈活,但相應(yīng)地會(huì)增加開發(fā)和部署的復(fù)雜度。
5.社區(qū)和生態(tài):Kafka、ActiveMQ、RabbitMQ和RocketMQ都擁有龐大的社區(qū)和完善的生態(tài)系統(tǒng),但Kafka和RocketMQ目前的發(fā)展勢(shì)頭比較迅猛,社區(qū)活躍度也相對(duì)較高。
6.功能支持:
總的來說,這些消息中間件都有自己的優(yōu)缺點(diǎn),選擇哪一種取決于具體的業(yè)務(wù)需求和系統(tǒng)架構(gòu)。
擴(kuò)展知識(shí)
如何選型
在選擇消息隊(duì)列技術(shù)時(shí),需要根據(jù)實(shí)際業(yè)務(wù)需求和系統(tǒng)特點(diǎn)來選擇,以下是一些參考因素:
1.性能和吞吐量:如果需要處理海量數(shù)據(jù),需要高性能和高吞吐量,那么Kafka是一個(gè)不錯(cuò)的選擇
2.可靠性:如果需要保證消息傳遞的可靠性,包括數(shù)據(jù)不丟失和消息不重復(fù)投遞,那么RocketMQ和RabbitMQ都提供了較好的可靠性保證。
3.消息傳遞模型:如果需要支持發(fā)布-訂閱和點(diǎn)對(duì)點(diǎn)模型,那么RocketMQ和RabbitMQ是一個(gè)不錯(cuò)的選擇。如果只需要發(fā)布-訂閱模型,Kafka則是一個(gè)更好的選擇
4.消息持久化:如果需要更快地持久化消息,并且支持高效的消息查詢,那么Kafka是一個(gè)不錯(cuò)的選擇。如果需要更加傳統(tǒng)的消息持久化方式,那么RocketMO和RabbitMO可以滿足需求
5.開發(fā)和部署復(fù)雜度:Kafka比較簡(jiǎn)單,易于使用和部署,但在實(shí)現(xiàn)一些高級(jí)功能時(shí)需要進(jìn)行一些復(fù)雜的配置RocketMQ和RabbitMQ提供了更多的功能和選項(xiàng),也更加靈活,但相應(yīng)地會(huì)增加開發(fā)和部署的復(fù)雜度。
6.社區(qū)和生態(tài):Kafka、RocketMQ和RabbitMQ都擁有龐大的社區(qū)和完善的生態(tài)系統(tǒng),但Kafka和RocketMO目前的發(fā)展勢(shì)頭比較迅猛,社區(qū)活躍度也相對(duì)較高。
7.實(shí)現(xiàn)語言方面,kafka是基于scala和java開發(fā)的,rocketmg、activemg等都是基于iava語言的,rabbitmg是基于erlang的。
8.功能性,上面列舉過一些功能,我們?cè)谶x型的時(shí)候需要看哪個(gè)可以滿足我們的需求,
需要根據(jù)具體情況來選擇最適合的消息隊(duì)列技術(shù)。如果有多個(gè)因素需要考慮,可以進(jìn)行性能測(cè)試和功能評(píng)估來輔助選擇。
Kafka 為什么這么快?
kafka是一個(gè)成熟的消息隊(duì)列,一直以性能高著稱,它之所以能夠?qū)崿F(xiàn)高吞吐量和低延遲,主要是由于以下幾個(gè)方面的優(yōu)化,我試著從發(fā)送端,存儲(chǔ)端以及消費(fèi)端分別介紹一下。
消息發(fā)送
1.批量發(fā)送:Kafka 通過將多個(gè)消息打包成一個(gè)批次,減少了網(wǎng)絡(luò)傳輸和磁盤寫入的次數(shù),從而提高了消息的吞吐量和傳輸效率。
2.異步發(fā)送:生產(chǎn)者可以異步發(fā)送消息,不必等待每個(gè)消息的確認(rèn),這大大提高了消息發(fā)送的效率。
3.消息壓縮:支持對(duì)消息進(jìn)行壓縮,減少網(wǎng)絡(luò)傳輸?shù)臄?shù)據(jù)量。
4.并行發(fā)送:通過將數(shù)據(jù)分布在不同的分區(qū)(Partitions)中,生產(chǎn)者可以并行發(fā)送消息,從而提高了吞吐量。
消息存儲(chǔ)
1.零拷貝技術(shù):Kafka 使用零拷貝技術(shù)來避免了數(shù)據(jù)的拷貝操作,降低了內(nèi)存和 CPU 的使用率,提高了系統(tǒng)的性能。
2.磁盤順序寫入:Kafka把消息存儲(chǔ)在磁盤上,且以順序的方式寫入數(shù)據(jù)。順序?qū)懭氡入S機(jī)寫入速度快很多,因?yàn)樗鼫p少了磁頭尋道時(shí)間。避免了隨機(jī)讀寫帶來的性能損耗,提高了磁盤的使用效率。
3.頁緩存:Kafka 將其數(shù)據(jù)存儲(chǔ)在磁盤中,但在訪問數(shù)據(jù)時(shí),它會(huì)先將數(shù)據(jù)加載到操作系統(tǒng)的頁緩存中,并在頁緩存中保留一份副本,從而實(shí)現(xiàn)快速的數(shù)據(jù)訪問。
4.稀疏索引:Kafka 存儲(chǔ)消息是通過分段的日志文件,每個(gè)分段都有自己的索引文件。這些索引文件中的條目不是對(duì)分段中的每條消息都建立索引,而是每隔一定數(shù)量的消息建立一個(gè)索引點(diǎn),這就構(gòu)成了稀疏索引。稀疏索引減少了索引大小,使得加載到內(nèi)存中的索引更小,提高了查找特定消息的效率
5.分區(qū)和副本:Kafka 采用分區(qū)和副本的機(jī)制,可以將數(shù)據(jù)分散到多個(gè)節(jié)點(diǎn)上進(jìn)行處理,從而實(shí)現(xiàn)了分布式的高可用性和負(fù)載均衡。
消息消費(fèi)
1.消費(fèi)者群組:通過消費(fèi)者群組可以實(shí)現(xiàn)消息的負(fù)載均衡和容錯(cuò)處理
2.并行消費(fèi):不同的消費(fèi)者可以獨(dú)立地消費(fèi)不同的分區(qū),實(shí)現(xiàn)消費(fèi)的并行處理。
3.批量拉取:Kafka支持批量拉取消息,可以一次性拉取多個(gè)消息進(jìn)行消費(fèi)。減少網(wǎng)絡(luò)消耗,提升性能
Kafka的架構(gòu)是怎么樣的?
典型回答
Kafka 的整體架構(gòu)比較簡(jiǎn)單,是顯式分布式架構(gòu),主要由 Producer(生產(chǎn)者)、broker(Kafka集群)和consumer(消費(fèi)者)組成
生產(chǎn)者(Producer):生產(chǎn)者負(fù)責(zé)將消息發(fā)布到Kafka集群中的一個(gè)或多個(gè)主題(Topic),每個(gè)Topic包含一個(gè)或多個(gè)分區(qū)(Partition)。
主題:Topic。主題是承載消息的邏輯容器,在實(shí)際使用中多用來區(qū)分具體的業(yè)務(wù)。
分區(qū):Partition。一個(gè)有序不變的消息序列。每個(gè)主題下可以有多個(gè)分區(qū)。
消費(fèi)者(Consumer):消費(fèi)者負(fù)責(zé)從Kafka集群中的一個(gè)或多個(gè)主題消費(fèi)消息,并將消費(fèi)的偏移量(Offset)提交回Kafka以保證消息的順序性和一致性。
偏移量:Offset。表示分區(qū)中每條消息的位置信息,是一個(gè)單調(diào)遞增且不變的值。
Kafka集群:Kafka集群是由多個(gè)Kafka節(jié)點(diǎn)(Broker)組成的分布式系統(tǒng)。每個(gè)節(jié)點(diǎn)都可以存儲(chǔ)一個(gè)或多個(gè)主題(topic)的分區(qū)(partition)副本,以提供高可用性和容錯(cuò)能力。
如下圖中,包含了 Broker1、Broker2和 Broker3組成了一個(gè)集群。用來提升高可用性。
**在集群中,每個(gè)分區(qū)(partition)都可以有多個(gè)副本。這些副本中包含了一個(gè)Leader(也可以叫做LeaderPartition 或者 Leader Replication)和多個(gè)Follower(也可以叫做Follower Partition 或者 FollowerReplication),****只有Leader 才能處理生產(chǎn)者和消費(fèi)者的請(qǐng)求,而Follower 只是Leader 的備份,用于提供數(shù)據(jù)的冗余備份和容錯(cuò)能力。**如果 Leader 發(fā)生故障,Kafka 集群會(huì)自動(dòng)將 Follower 提升為新的 Leader,從而實(shí)現(xiàn)高可用性和容錯(cuò)能力。
ZooKeeper:ZooKeeper是Kafka集群中使用的分布式協(xié)調(diào)服務(wù),用于維護(hù)Kafka集群的狀態(tài)和元數(shù)據(jù)信息,例如主題和分區(qū)的分配信息、消費(fèi)者組和消費(fèi)者偏移量等。
Kafka如何保證消息不丟失?
典型回答
Kafka作為一個(gè)消息中間件,他需要結(jié)合消息生產(chǎn)者和消費(fèi)者一起才能工作,一次消息發(fā)送包含以下是三個(gè)過程
1)Producer 端發(fā)送消息給 Kafka Broker
2)Kafka Broker 將消息進(jìn)行同步并持久化數(shù)據(jù).
3)Consumer端從Kafka Broker 將消息拉取并進(jìn)行消費(fèi),
Kafka只對(duì)已提交的消息做最大限度的持久化保證不丟失,但是沒辦法保證100%。
但是,Kafka還是提供了很多機(jī)制來保證消息不丟失的。要想知道Kafka如何保證消息不丟失,需要從生產(chǎn)者、消費(fèi)者以及kafka集群三個(gè)方面來分析。
1、生產(chǎn)者:當(dāng)我們采用異步發(fā)送的時(shí)候,可以設(shè)置一個(gè)回調(diào)函數(shù),如果發(fā)送失敗,會(huì)進(jìn)行重試。并且使用acks機(jī)制,比如acks=-1,就必須保證消息寫入了所有的同步副本才寫入成功,否則就會(huì)重試。
2、Broker集群:①具有消息的持久化機(jī)制,當(dāng)消息被寫入消息隊(duì)列后,會(huì)被持久化到磁盤。②有同步副本:每個(gè)分區(qū)都有多個(gè)副本,副本可以分布在不同的節(jié)點(diǎn)上。當(dāng)一個(gè)節(jié)點(diǎn)宕機(jī)時(shí),其他節(jié)點(diǎn)上的副本仍然可以提供服務(wù),保證消息不丟失。
3、消費(fèi)者:①消費(fèi)者記錄每個(gè)分區(qū)消息消費(fèi)的偏移量,每次都會(huì)記錄下來,為了保證消息不丟失,建議使用手動(dòng)提交偏移量的方式,避免拉取了消息以后,業(yè)務(wù)邏輯沒處理完,提交偏移量后但是消費(fèi)者掛了的問題。②Kafka消費(fèi)者還可以組成消費(fèi)者組,每個(gè)消費(fèi)者組可以同時(shí)消費(fèi)多個(gè)分區(qū)。當(dāng)一個(gè)消費(fèi)者組中的消費(fèi)者宕機(jī)或者不可用時(shí),其他消費(fèi)者仍然可以消費(fèi)該組的分區(qū),保證消息不丟失,
Producer
消息的生產(chǎn)者端,最怕的就是消息發(fā)送給Kafka集群的過程中失敗,所以,我們需要有機(jī)制來確保消息能夠發(fā)送成功,但是,因?yàn)榇嬖诰W(wǎng)絡(luò)問題,所以基本沒有什么辦法可以保證一次消息一定能成功。
所以,就需要有一個(gè)確認(rèn)機(jī)制來告訴生產(chǎn)者這個(gè)消息是否有發(fā)送成功,如果沒成功,需要重新發(fā)送直到成功。
我們通常使用Kafka發(fā)送消息的時(shí)候,通常使用的 producer.send(msg)其實(shí)是一種異步發(fā)送,發(fā)送消息的時(shí)候,方法會(huì)立即返回,但是并不代表消息一定能發(fā)送成功。(producer.send(msg).get() 是同步等待返回的。)
那么,為了保證消息不丟失,通常會(huì)建議**使用 producer.send(msg,callback)方法,**這個(gè)方法支持傳入一個(gè)callback,我們可以在消息發(fā)送時(shí)進(jìn)行重試。
同時(shí),我們也可以通過給producer設(shè)置一些參數(shù)來提升發(fā)送成功率:
Broker
Kafka的集群有一些機(jī)制來保證消息的不丟失,比如復(fù)制機(jī)制、持久化存儲(chǔ)機(jī)制以及ISR機(jī)制。
·持久化存儲(chǔ):Kafka使用持久化存儲(chǔ)來存儲(chǔ)消息。這意味著消息在寫入Kafka時(shí)將被寫入磁盤,這種方式可以防止消息因?yàn)楣?jié)點(diǎn)宕機(jī)而丟失。
·ISR復(fù)制機(jī)制:Kafka使用ISR機(jī)制來確保消息不會(huì)丟失,Kafka使用復(fù)制機(jī)制來保證數(shù)據(jù)的可靠性。每個(gè)分區(qū)都有多個(gè)副本,副本可以分布在不同的節(jié)點(diǎn)上。當(dāng)一個(gè)節(jié)點(diǎn)宕機(jī)時(shí),其他節(jié)點(diǎn)上的副本仍然可以提供服務(wù),保證消息不丟失。
在服務(wù)端,也有一些參數(shù)配置可以調(diào)節(jié)來避免消息丟失:
Consumer
作為Kafka的消費(fèi)者端,只需要確保投遞過來的消息能正常消費(fèi),并且不會(huì)胡亂的提交偏移量就行了。
Kafka消費(fèi)者會(huì)跟蹤每個(gè)分區(qū)的偏移量,消費(fèi)者每次消費(fèi)消息時(shí),都會(huì)將偏移量向后移動(dòng)。當(dāng)消費(fèi)者宕機(jī)或者不可用時(shí),Kafka會(huì)將該消費(fèi)者所消費(fèi)的分區(qū)的偏移量保存下來,下次該消費(fèi)者重新啟動(dòng)時(shí),可以從上一次的偏移量開始消費(fèi)消息。
另外,Kafka消費(fèi)者還可以組成消費(fèi)者組,每個(gè)消費(fèi)者組可以同時(shí)消費(fèi)多個(gè)分區(qū)。當(dāng)一個(gè)消費(fèi)者組中的消費(fèi)者宕機(jī)或者不可用時(shí),其他消費(fèi)者仍然可以消費(fèi)該組的分區(qū),保證消息不丟失,
為了保證消息不丟失,建議使用手動(dòng)提交偏移量的方式,避免拉取了消息以后,業(yè)務(wù)邏輯沒處理完,提交偏移量后但是消費(fèi)者掛了的問題:
Kafka怎么保證消費(fèi)只消費(fèi)一次的?(防止重復(fù)消費(fèi))
典型回答
Kafka消息只消費(fèi)一次,這個(gè)需要從多方面回答,既包含Kafka自身的機(jī)制,也需要考慮客戶端自己的重復(fù)處理。
可以從以下幾個(gè)方面回答:
首先,在Kafka中,每個(gè)消費(fèi)者都必須加入至少一個(gè)消費(fèi)者組。同一個(gè)消費(fèi)者組內(nèi)的消費(fèi)者可以共享消費(fèi)者的負(fù)載。因此,如果一個(gè)消息被消費(fèi)組中的任何一個(gè)消費(fèi)者消費(fèi)了,那么其他消費(fèi)者就不會(huì)再收到這個(gè)消息了。
另外,消費(fèi)者可以通過手動(dòng)提交消費(fèi)位移來控制消息的消費(fèi)情況。通過手動(dòng)提交位移,消費(fèi)者可以跟蹤自己已經(jīng)消費(fèi)的消息,確保不會(huì)重復(fù)消費(fèi)同一消息。
還有就是客戶端自己可以做一些冪等機(jī)制,防止消息的重復(fù)消費(fèi)。
另外可以借助Kafka的Exactly-once消費(fèi)語義,其實(shí)就是引入了事務(wù),消費(fèi)者使用事務(wù)來保證消息的消費(fèi)和位移提交是原子的,而生產(chǎn)者可以使用事務(wù)來保證消息的生產(chǎn)和位移提交是原子的。Exactly-once消費(fèi)語義則解決了重復(fù)問題,但需要更復(fù)雜的設(shè)置和配置。
回答:
1、首先kafka使用消費(fèi)者組的機(jī)制,可以確保如果一個(gè)消息被消費(fèi)組中的任何一個(gè)消費(fèi)者消費(fèi)了,那么其他消費(fèi)者就不會(huì)再收到這個(gè)消息了。
2、使用kafka的消息語義Exactly-once,它是使用了事務(wù)來保證消息的消費(fèi)和位移提交是原子的,不會(huì)說消費(fèi)了消息但是位移提交失敗,并且生產(chǎn)者使用事務(wù)來保證消息的生產(chǎn)和位移提交是原子的,不會(huì)重復(fù)發(fā)送消息。
3、客戶端做一些冪等機(jī)制,使得消息即使重復(fù)消費(fèi)了,最后的結(jié)果也是一樣的。
擴(kuò)展知識(shí)
Kafka的三種消息傳遞語義
在Kafka中,有三種常見的消息傳遞語義:At-least-once、At-most-once和Exactly-once。其中At-least-once和Exactly-once是最常用的。
At-least-once消費(fèi)語義
At-least-once消費(fèi)語義意味著消費(fèi)者至少消費(fèi)一次消息,但可能會(huì)重復(fù)消費(fèi)同一消息。在At-least-once語義中,當(dāng)消費(fèi)者從Kafka服務(wù)器讀取消息時(shí),消息的偏移量會(huì)被記錄下來。一旦消息被成功處理,消費(fèi)者會(huì)將位移提交回Kafka服務(wù)器。如果消費(fèi)消息成功但是提交位移失敗,這意味著該消息將在下一次重試時(shí)再次被消費(fèi)。
At-least-once語義通常用于實(shí)時(shí)數(shù)據(jù)處理或消費(fèi)者不能容忍數(shù)據(jù)丟失的場(chǎng)景,例如金融交易或電信信令。
Exactly-once消費(fèi)語義
Exactly-once消費(fèi)語義意味著每個(gè)消息僅被消費(fèi)一次,且不會(huì)被重復(fù)消費(fèi)。在Exactly-once語義中,Kafka保證消息只被處理一次,同時(shí)保持消息的順序性。為了實(shí)現(xiàn)Exactly-once語義,Kafka引入了一個(gè)新的概念:事務(wù)。
事務(wù)是一系列的讀寫操作,這些操作要么全部成功,要么全部失敗。在Kafka中,生產(chǎn)者和消費(fèi)者都可以使用事務(wù),以保證消息的Exactly-once語義。具體來說,消費(fèi)者可以使用事務(wù)來保證消息的消費(fèi)和位移提交是原子的而生產(chǎn)者可以使用事務(wù)來保證消息的生產(chǎn)和位移提交是原子的。
在Kafka 0.11版本之前,實(shí)現(xiàn)Exactly-once語義需要一些特殊的配置和設(shè)置。但是,在Kafka 0.11版本之后Kafka提供了原生的Exactly-once支持,使得實(shí)現(xiàn)Exactly-once變得更加簡(jiǎn)單和可靠。
總之,At-least-once消費(fèi)語義保證了數(shù)據(jù)的可靠性,但可能會(huì)導(dǎo)致數(shù)據(jù)重復(fù)。而Exactly-once消費(fèi)語義則解決了重復(fù)問題,但需要更復(fù)雜的設(shè)置和配置。選擇哪種消費(fèi)語義取決于業(yè)務(wù)需求和數(shù)據(jù)可靠性要求。