kafka丢消息
kafka會(huì)丟消息主要集中在兩個(gè)環(huán)節(jié)
消息落盤時(shí)機(jī)
消息落盤有異步刷新和同步刷新兩種,明顯異步刷新的可靠性要高很多。但在某些場(chǎng)景下追求性能而忽略可靠性,可以啟用。
消息存儲(chǔ)維護(hù)
持久化存儲(chǔ),這句話不是說(shuō)來(lái)玩的。Oracle/MySQL做了這么久的存儲(chǔ),其中的災(zāi)難恢復(fù)工具等都非常完備并形成體系(出問題你能找到人并能解決問題)kafka的存儲(chǔ)誰(shuí)特么知道~工具又特么的少!
另外就是落盤的存儲(chǔ)介質(zhì),如果不做raid,那么單盤存在損壞的可能;做了raid,則成本上升。如果做多集copy,則存在網(wǎng)絡(luò)同步延時(shí)所帶來(lái)的瞬間數(shù)據(jù)不一致。
小結(jié):kafka你要做到完全不丟數(shù)據(jù)(在非大災(zāi)大難的情況下,比如機(jī)房被原子彈轟炸;或者raid被誤操作弄錯(cuò)同步時(shí)間或者低格等),是完全可以的。代價(jià)就是丟失一定的性能。
所以kafka我一般用在業(yè)務(wù)允許少量數(shù)據(jù)丟失但整體吞吐量非常大的場(chǎng)景(比如日志采集),數(shù)據(jù)統(tǒng)計(jì)分析(卻少幾百條數(shù)據(jù)不會(huì)對(duì)億萬(wàn)級(jí)的樣本空間產(chǎn)生什么影響)。
kafka也可以用在兩個(gè)可靠存儲(chǔ)之間做數(shù)據(jù)同步,比如MySQL(寫)->MySQL(度),因?yàn)镸ySQL(寫)保證了數(shù)據(jù)可被重放,所以kafka出問題時(shí)恢復(fù)速度和恢復(fù)可靠程度是可以得到保證的
?
kafka環(huán)節(jié)丟失數(shù)據(jù),常見的kafka環(huán)節(jié)丟失數(shù)據(jù)的原因有:
如果auto.commit.enable=true,當(dāng)consumer fetch了一些數(shù)據(jù)但還沒有完全處理掉的時(shí)候,剛好到commit interval出發(fā)了提交offset操作,接著consumer crash掉了。這時(shí)已經(jīng)fetch的數(shù)據(jù)還沒有處理完成但已經(jīng)被commit掉,因此沒有機(jī)會(huì)再次被處理,數(shù)據(jù)丟失。
網(wǎng)絡(luò)負(fù)載很高或者磁盤很忙寫入失敗的情況下,沒有自動(dòng)重試重發(fā)消息。沒有做限速處理,超出了網(wǎng)絡(luò)帶寬限速。kafka一定要配置上消息重試的機(jī)制,并且重試的時(shí)間間隔一定要長(zhǎng)一些,默認(rèn)1秒鐘并不符合生產(chǎn)環(huán)境(網(wǎng)絡(luò)中斷時(shí)間有可能超過(guò)1秒)。
如果磁盤壞了,會(huì)丟失已經(jīng)落盤的數(shù)據(jù)
單批數(shù)據(jù)的長(zhǎng)度超過(guò)限制會(huì)丟失數(shù)據(jù),報(bào)kafka.common.MessageSizeTooLargeException異常
解決:
partition leader在未完成副本數(shù)follows的備份時(shí)就宕機(jī)的情況,即使選舉出了新的leader但是已經(jīng)push的數(shù)據(jù)因?yàn)槲磦浞菥蛠G失了!
kafka是多副本的,當(dāng)你配置了同步復(fù)制之后。多個(gè)副本的數(shù)據(jù)都在PageCache里面,出現(xiàn)多個(gè)副本同時(shí)掛掉的概率比1個(gè)副本掛掉的概率就很小了。(官方推薦是通過(guò)副本來(lái)保證數(shù)據(jù)的完整性的)
kafka的數(shù)據(jù)一開始就是存儲(chǔ)在PageCache上的,定期flush到磁盤上的,也就是說(shuō),不是每個(gè)消息都被存儲(chǔ)在磁盤了,如果出現(xiàn)斷電或者機(jī)器故障等,PageCache上的數(shù)據(jù)就丟失了。
可以通過(guò)log.flush.interval.messages和log.flush.interval.ms來(lái)配置flush間隔,interval大丟的數(shù)據(jù)多些,小會(huì)影響性能但在0.8版本,可以通過(guò)replica機(jī)制保證數(shù)據(jù)不丟,代價(jià)就是需要更多資源,尤其是磁盤資源,kafka當(dāng)前支持GZip和Snappy壓縮,來(lái)緩解這個(gè)問題 是否使用replica取決于在可靠性和資源代價(jià)之間的balance
?
消息發(fā)送方式
想清楚Kafka發(fā)送的消息是否丟失,需要先了解Kafka消息的發(fā)送方式。
Kafka消息發(fā)送分同步(sync)、異步(async)兩種方式
默認(rèn)是使用同步方式,可通過(guò)producer.type屬性進(jìn)行配置;
Kafka保證消息被安全生產(chǎn),有三個(gè)選項(xiàng)分別是0,1,-1
通過(guò)request.required.acks屬性進(jìn)行配置:
0代表:不進(jìn)行消息接收是否成功的確認(rèn)(默認(rèn)值);
1代表:當(dāng)Leader副本接收成功后,返回接收成功確認(rèn)信息;
-1代表:當(dāng)Leader和Follower副本都接收成功后,返回接收成功確認(rèn)信息;
六種發(fā)送場(chǎng)景
兩個(gè)維度相交,生成六種情況,如下圖:
?
消息丟失的場(chǎng)景
網(wǎng)絡(luò)異常
acks設(shè)置為0時(shí),不和Kafka集群進(jìn)行消息接受確認(rèn),當(dāng)網(wǎng)絡(luò)發(fā)生異常等情況時(shí),存在消息丟失的可能;
客戶端異常
異步發(fā)送時(shí),消息并沒有直接發(fā)送至Kafka集群,而是在Client端按一定規(guī)則緩存并批量發(fā)送。在這期間,如果客戶端發(fā)生死機(jī)等情況,都會(huì)導(dǎo)致消息的丟失;
緩沖區(qū)滿了
異步發(fā)送時(shí),Client端緩存的消息超出了緩沖池的大小,也存在消息丟失的可能;
Leader副本異常
acks設(shè)置為1時(shí),Leader副本接收成功,Kafka集群就返回成功確認(rèn)信息,而Follower副本可能還在同步。這時(shí)Leader副本突然出現(xiàn)異常,新Leader副本(原Follower副本)未能和其保持一致,就會(huì)出現(xiàn)消息丟失的情況;
以上就是消息丟失的幾種情況,在日常應(yīng)用中,我們需要結(jié)合自身的應(yīng)用場(chǎng)景來(lái)選擇不同的配置。
想要更高的吞吐量就設(shè)置:異步、ack=0;想要不丟失消息數(shù)據(jù)就選:同步、ack=-1策略
附:Kafka備份策略,不理解的可以看我的另一篇文章《Kafka消息的備份策略》
總結(jié)
- 上一篇: Redis架构及分片管理
- 下一篇: Kafka的优化建议