四、保證消息隊(duì)列的高可用
以RCOKETMQ為例,它的集群就有多master模式右钾、多master多slave異步復(fù)制模式轻要、多master多slave同步雙寫模式复旬。和kafka好像,只是NameServer集群冲泥,在kafka中用zookeeper代替驹碍,都是用來保存和發(fā)現(xiàn)master和slave用的,通信過程如下:
Producer與NameServer集群中的其中一個(gè)節(jié)點(diǎn)(隨機(jī))建立長連接凡恍,定期從NameServer獲取Topic路由信息志秃,并向提供Topic服務(wù)的Broker Master和Slave建立長連接,即可以從Broker Master訂閱消息嚼酝,也可以從Broker Slave訂閱消息洽损。
一個(gè)典型的Kafka集群中包含若干Producer(可以是web前端產(chǎn)生的page view,或者是服務(wù)器日志革半,系統(tǒng)cpu碑定,memory等),若干broker(Kafka支持水平擴(kuò)展又官,一般broker數(shù)量越多延刘,集群吞吐率越高),若干Consumer Group六敬,以及一個(gè)Zookeeper集群碘赖。Kafka通過broker,Consumer使用pull模式從broker訂閱并消費(fèi)消息外构。
五普泡、如何保證不會重復(fù)消費(fèi)
1、RabbitMQ會發(fā)生一個(gè)ACK確認(rèn)消息
2审编、RocketMQ會返回一個(gè)CONSUME_SUCCESS成功標(biāo)志
3撼班、Kafka每條消息會有一個(gè)offset,在消費(fèi)后需要提交offset垒酬,讓消息隊(duì)列知道已經(jīng)消費(fèi)
六砰嘁、如何保證消息的可靠傳輸
分析:在使用消息隊(duì)列過程中,應(yīng)該做到消息不能多消費(fèi)勘究,也不能少消費(fèi)矮湘。
三個(gè)角度:生產(chǎn)者弄丟數(shù)據(jù)、消息隊(duì)列弄丟數(shù)據(jù)口糕、消費(fèi)者弄丟數(shù)據(jù)
RabbitMQ
RabbitMQ提供transaction和confirm來保證生產(chǎn)者不丟消息
1.1 transaction機(jī)制就是說在發(fā)送消息的時(shí)候開啟事務(wù)<channel.txSelect()>缅阳,然后再發(fā)送消息,若發(fā)送過程中發(fā)生異常則回滾<channel.txRollback()>景描,成功則提交<channel.txCommit()>十办,缺點(diǎn)就是吞吐量下降
1.2 confirm模式生產(chǎn)上用的居多孤里,一旦channel進(jìn)入confirm模式,所有在該信道上的消息都會被指派一個(gè)唯一ID(從1開始)橘洞,一旦消息投遞到所匹配的隊(duì)列都捌袜,RabbitMQ會發(fā)送一個(gè)Ack(包含消息的唯一ID)給生產(chǎn)者,這就知道已經(jīng)消費(fèi)處理了炸枣,如果RabbitMQ沒有處理這條消息虏等,則會發(fā)送一個(gè)Nack消息給你,這就知道消費(fèi)失敗适肠,然后就可以重試了霍衫。
RabbitMQ消息隊(duì)列丟數(shù)據(jù)
2.1 處理消息隊(duì)列丟數(shù)據(jù)的情況,一般是開啟持久化磁盤的配置侯养。這個(gè)持久化配置可以和confirm機(jī)制配合使用敦跌,你可以在消息持久化磁盤后,再給生產(chǎn)者發(fā)送一個(gè)Ack信號逛揩。這樣柠傍,如果消息持久化磁盤之前,rabbitMQ陣亡了辩稽,那么生產(chǎn)者收不到Ack信號惧笛,生產(chǎn)者會自動重發(fā)。
2.11 那么如何持久化呢逞泄,這里順便說一下吧患整,其實(shí)也很容易,就下面兩步
2.11 1. 將queue的持久化標(biāo)識durable設(shè)置為true,則代表是一個(gè)持久的隊(duì)列
2.11 2. 發(fā)送消息的時(shí)候?qū)eliveryMode=2
這樣設(shè)置以后喷众,rabbitMQ就算掛了各谚,重啟后也能恢復(fù)數(shù)據(jù)
RabbitMQ消費(fèi)者丟數(shù)據(jù)
3.1 消費(fèi)者丟數(shù)據(jù)一般是因?yàn)椴捎昧俗詣哟_認(rèn)消息模式(采用手動提交即可)
Kafka
Producer在發(fā)布消息到某個(gè)Partition時(shí),先通過zookeeper找到該partition的leader到千,然后無論該topic的replication factor為多少(也即該partition有多少個(gè)replication)昌渤,Producer只將該消息發(fā)送到該P(yáng)artition的leader,leader會將該消息寫入本地log父阻,每個(gè)Follower都從Leader中pull數(shù)據(jù)愈涩。
Kafka生產(chǎn)丟失數(shù)據(jù)
4.1 在kafka生產(chǎn)中望抽,基本都有一個(gè)leader和多個(gè)follwer加矛。follwer會去同步leader的信息。因此煤篙,為了避免生產(chǎn)者丟數(shù)據(jù)斟览,做如下兩點(diǎn)配置
第一個(gè)配置要在producer端設(shè)置acks=all。這個(gè)配置保證了辑奈,follwer同步完成后苛茂,才認(rèn)為消息發(fā)送成功已烤。
在producer端設(shè)置retries=MAX,一旦寫入失敗妓羊,這無限重試
Kafka消息隊(duì)列丟數(shù)據(jù)
5.1 針對消息隊(duì)列丟數(shù)據(jù)的情況胯究,無外乎就是,數(shù)據(jù)還沒同步躁绸,leader就掛了裕循,這時(shí)zookpeer會將其他的follwer切換為leader,那數(shù)據(jù)就丟失了。針對這種情況净刮,應(yīng)該做兩個(gè)配置剥哑。
replication.factor參數(shù),這個(gè)值必須大于1淹父,即要求每個(gè)partition必須有至少2個(gè)副本
min.insync.replicas參數(shù)株婴,這個(gè)值必須大于1,這個(gè)是要求一個(gè)leader至少感知到有至少一個(gè)follower還跟自己保持聯(lián)系暑认。這兩個(gè)配置加上上面生產(chǎn)者的配置聯(lián)合起來用困介,基本可確保kafka不丟數(shù)據(jù)
Kafka消費(fèi)者丟數(shù)據(jù)
6.1 這種情況一般是自動提交了offset,然后你處理程序過程中掛了蘸际。kafka以為你處理好了逻翁。解決方案也很簡單,改成手動提交即可捡鱼。
6.2 offset介紹:
6.21 offset:指的是kafka的topic中的每個(gè)消費(fèi)組消費(fèi)的下標(biāo)八回。簡單的來說就是一條消息對應(yīng)一個(gè)offset下標(biāo),每次消費(fèi)數(shù)據(jù)的時(shí)候如果提交offset驾诈,那么下次消費(fèi)就會從提交的offset加一那里開始消費(fèi)缠诅。
比如一個(gè)topic中有100條數(shù)據(jù),我消費(fèi)了50條并且提交了乍迄,那么此時(shí)的kafka服務(wù)端記錄提交的offset就是49(offset從0開始)管引,那么下次消費(fèi)的時(shí)候offset就從50開始消費(fèi)。