色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

盤點(diǎn)Kafka一些非比尋常的坑

Linux愛(ài)好者 ? 來(lái)源:ImportNew ? 作者:ImportNew ? 2021-11-13 15:33 ? 次閱讀

前言

我的上家公司是做餐飲系統(tǒng)的,每天中午和晚上用餐高峰期,系統(tǒng)的并發(fā)量不容小覷。為了保險(xiǎn)起見(jiàn),公司規(guī)定各部門都要在吃飯的時(shí)間輪流值班,防止出現(xiàn)線上問(wèn)題時(shí)能夠及時(shí)處理。

我當(dāng)時(shí)在后廚顯示系統(tǒng)團(tuán)隊(duì),該系統(tǒng)屬于訂單的下游業(yè)務(wù)。

用戶點(diǎn)完菜下單后,訂單系統(tǒng)會(huì)通過(guò)發(fā) Kafka 消息給我們系統(tǒng);

系統(tǒng)讀取消息后,做業(yè)務(wù)邏輯處理,持久化訂單和菜品數(shù)據(jù),然后展示到劃菜客戶端;

這樣廚師就知道哪個(gè)訂單要做哪些菜,有些菜做好了,就可以通過(guò)該系統(tǒng)出菜;

系統(tǒng)自動(dòng)通知服務(wù)員上菜;

如果服務(wù)員上完菜,修改菜品上菜狀態(tài),用戶就知道哪些菜已經(jīng)上了,哪些還沒(méi)有上。

這個(gè)系統(tǒng)可以大大提高后廚到用戶的效率。

事實(shí)證明,這一切的關(guān)鍵是消息中間件:Kafka。如果它有問(wèn)題,將會(huì)直接影響到后廚顯示系統(tǒng)的功能。

接下來(lái),我跟大家一起聊聊使用 Kafka 兩年時(shí)間踩過(guò)哪些坑?

1. 順序問(wèn)題

1.1 為什么要保證消息的順序?

剛開(kāi)始我們系統(tǒng)的商戶很少,為了快速實(shí)現(xiàn)功能,我們沒(méi)想太多。既然是走消息中間件 Kafka 通信,訂單系統(tǒng)發(fā)消息時(shí)將訂單詳細(xì)數(shù)據(jù)放在消息體,我們后廚顯示系統(tǒng)只要訂閱 topic,就能獲取相關(guān)消息數(shù)據(jù),然后處理自己的業(yè)務(wù)即可。

不過(guò)這套方案有個(gè)關(guān)鍵因素:要保證消息的順序。

為什么呢?

訂單有很多狀態(tài),比如下單、支付、完成、撤銷等。不可能下單的消息都沒(méi)讀取到,就先讀取支付或撤銷的消息吧。如果真的這樣,數(shù)據(jù)不是會(huì)產(chǎn)生錯(cuò)亂?

好吧,看來(lái)保證消息順序是有必要的。

1.2 如何保證消息順序?

我們都知道 Kafka 的 topic 是無(wú)序的,但是一個(gè) topic 包含多個(gè) partition,每個(gè) partition 內(nèi)部是有序的。

如此一來(lái),思路就變得清晰了:只要保證生產(chǎn)者寫消息時(shí),按照一定的規(guī)則寫到同一個(gè) partition。不同的消費(fèi)者讀不同的 partition 的消息,就能保證生產(chǎn)和消費(fèi)者消息的順序。

我們剛開(kāi)始就是這么做的,同一個(gè)商戶編號(hào)的消息寫到同一個(gè) partition。topic 中創(chuàng)建了 4 個(gè) partition,然后部署了 4 個(gè)消費(fèi)者節(jié)點(diǎn),構(gòu)成消費(fèi)者組。一個(gè) partition 對(duì)應(yīng)一個(gè)消費(fèi)者節(jié)點(diǎn)。

從理論上說(shuō),這套方案是能夠保證消息順序的。

一切規(guī)劃得看似“天衣無(wú)縫”,我們就這樣”順利“上線了。

1.3 出現(xiàn)意外

該功能上線了一段時(shí)間,剛開(kāi)始還是比較正常的。

但是,好景不長(zhǎng),很快就收到用戶投訴,說(shuō)在劃菜客戶端有些訂單和菜品一直看不到,無(wú)法劃菜。

我定位到了原因,公司在那段時(shí)間網(wǎng)絡(luò)經(jīng)常不穩(wěn)定,業(yè)務(wù)接口時(shí)不時(shí)報(bào)超時(shí),業(yè)務(wù)請(qǐng)求時(shí)不時(shí)會(huì)連不上數(shù)據(jù)庫(kù)。

這種情況對(duì)順序消息的打擊,可以說(shuō)是毀滅性的。

為什么這么說(shuō)?

假設(shè)訂單系統(tǒng)發(fā)了“下單”、“支付”、“完成” 三條消息。

而”下單“消息由于網(wǎng)絡(luò)原因我們系統(tǒng)處理失敗了,而后面的兩條消息的數(shù)據(jù)是無(wú)法入庫(kù)的。因?yàn)橹挥小毕聠巍跋⒌臄?shù)據(jù)才是完整的數(shù)據(jù),其他類型的消息只會(huì)更新?tīng)顟B(tài)。

加上我們當(dāng)時(shí)沒(méi)有做失敗重試機(jī)制,使得這個(gè)問(wèn)題被放大了。問(wèn)題變成:一旦“下單”消息的數(shù)據(jù)入庫(kù)失敗,用戶就永遠(yuǎn)看不到這個(gè)訂單和菜品了。

那么這個(gè)緊急的問(wèn)題要如何解決呢?

1.4 解決過(guò)程

最開(kāi)始我們的想法是:在消費(fèi)者處理消息時(shí),如果處理失敗了,立馬重試 3-5 次。

但如果有些請(qǐng)求要第 6 次才能成功怎么辦?

不可能一直重試呀,這種同步重試機(jī)制,會(huì)阻塞其他商戶訂單消息的讀取。

顯然,用上面的這種同步重試機(jī)制在出現(xiàn)異常的情況,會(huì)嚴(yán)重影響消息消費(fèi)者的消費(fèi)速度,降低它的吞吐量。

如此看來(lái),我們不得不用異步重試機(jī)制了。

如果用異步重試機(jī)制,處理失敗的消息就得保存到重試表下來(lái)。

但有個(gè)新問(wèn)題立馬出現(xiàn):只存一條消息如何保證順序?

存一條消息的確無(wú)法保證順序,假如“下單”消息失敗了,還沒(méi)來(lái)得及異步重試。此時(shí),“支付”消息被消費(fèi)了,它肯定是不能被正常消費(fèi)的。

此時(shí),“支付”消息該一直等著,每隔一段時(shí)間判斷一次,它前面的消息都有沒(méi)有被消費(fèi)?

如果真的這么做,會(huì)出現(xiàn)兩個(gè)問(wèn)題:

“支付”消息前面只有“下單”消息,這種情況比較簡(jiǎn)單。但如果某種類型的消息,前面有 N 多種消息,需要判斷多少次呀?這種判斷跟訂單系統(tǒng)的耦合性太強(qiáng)了,相當(dāng)于要把他們系統(tǒng)的邏輯搬一部分到我們系統(tǒng);

影響消費(fèi)者的消費(fèi)速度。

這時(shí)有種更簡(jiǎn)單的方案浮出水面:消費(fèi)者在處理消息時(shí),先判斷該訂單號(hào)在重試表有沒(méi)有數(shù)據(jù),如果有則直接把當(dāng)前消息保存到重試表;如果沒(méi)有,則進(jìn)行業(yè)務(wù)處理,如果出現(xiàn)異常,把該消息保存到重試表。

后來(lái)我們用 elastic-job 建立了失敗重試機(jī)制,如果重試了 7 次后還是失敗,則將該消息的狀態(tài)標(biāo)記為失敗,發(fā)郵件通知開(kāi)發(fā)人員。

終于由于網(wǎng)絡(luò)不穩(wěn)定,導(dǎo)致用戶在劃菜客戶端有些訂單和菜品一直看不到的問(wèn)題被解決了。現(xiàn)在商戶頂多偶爾延遲看到菜品,比一直看不菜品好太多。

2. 消息積壓

隨著銷售團(tuán)隊(duì)的市場(chǎng)推廣,我們系統(tǒng)的商戶越來(lái)越多。隨之而來(lái)的是消息的數(shù)量越來(lái)越大,導(dǎo)致消費(fèi)者處理不過(guò)來(lái),經(jīng)常出現(xiàn)消息積壓的情況。

對(duì)商戶的影響非常直觀,劃菜客戶端上的訂單和菜品可能半個(gè)小時(shí)后才能看到。一兩分鐘還能忍,半個(gè)消息的延遲,對(duì)有些暴脾氣的商戶哪里忍得了,馬上投訴過(guò)來(lái)了。我們那段時(shí)間經(jīng)常接到商戶投訴說(shuō)訂單和菜品有延遲。

雖說(shuō)加服務(wù)器節(jié)點(diǎn)就能解決問(wèn)題,但是按照公司為了省錢的慣例,要先做系統(tǒng)優(yōu)化,所以我們開(kāi)始了消息積壓?jiǎn)栴}解決之旅。

2.1 消息體過(guò)大

雖說(shuō) Kafka 號(hào)稱支持百萬(wàn)級(jí)的 TPS,但從 producer 發(fā)送消息到 broker 需要一次網(wǎng)絡(luò) IO,broker 寫數(shù)據(jù)到磁盤需要一次磁盤 IO(寫操作),consumer 從 broker 獲取消息先經(jīng)過(guò)一次磁盤 IO(讀操作),再經(jīng)過(guò)一次網(wǎng)絡(luò) IO。

一次簡(jiǎn)單的消息從生產(chǎn)到消費(fèi)過(guò)程,需要經(jīng)過(guò)兩次網(wǎng)絡(luò) IO 和兩次磁盤 IO。如果消息體過(guò)大,勢(shì)必會(huì)增加 IO 的耗時(shí),進(jìn)而影響 Kafka 生產(chǎn)和消費(fèi)的速度。消費(fèi)者速度太慢的結(jié)果,就會(huì)出現(xiàn)消息積壓情況。

除了上面的問(wèn)題之外,消息體過(guò)大還會(huì)浪費(fèi)服務(wù)器的磁盤空間。稍不注意,可能會(huì)出現(xiàn)磁盤空間不足的情況。

此時(shí),我們已經(jīng)到了需要優(yōu)化消息體過(guò)大問(wèn)題的時(shí)候。

如何優(yōu)化呢?

我們重新梳理了一下業(yè)務(wù),沒(méi)有必要知道訂單的中間狀態(tài),只需知道一個(gè)最終狀態(tài)就可以了。

如此甚好,我們就可以這樣設(shè)計(jì)了:

訂單系統(tǒng)發(fā)送的消息體只用包含 id 和狀態(tài)等關(guān)鍵信息

后廚顯示系統(tǒng)消費(fèi)消息后,通過(guò) id 調(diào)用訂單系統(tǒng)的訂單詳情查詢接口獲取數(shù)據(jù);

后廚顯示系統(tǒng)判斷數(shù)據(jù)庫(kù)中是否有該訂單的數(shù)據(jù),如果沒(méi)有則入庫(kù),有則更新。

果然這樣調(diào)整之后,消息積壓?jiǎn)栴}很長(zhǎng)一段時(shí)間都沒(méi)再出現(xiàn)。

2.2 路由規(guī)則不合理

還真別高興的太早,有天中午又有商戶投訴說(shuō)訂單和菜品有延遲。我們一查 Kafka 的 topic 竟然又出現(xiàn)了消息積壓。

但這次有點(diǎn)詭異,不是所有 partition 上的消息都有積壓,而是只有一個(gè)。

剛開(kāi)始,我以為是消費(fèi)那個(gè) partition 消息的節(jié)點(diǎn)出了什么問(wèn)題導(dǎo)致的。但是經(jīng)過(guò)排查,沒(méi)有發(fā)現(xiàn)任何異常。

這就奇怪了,到底哪里有問(wèn)題呢?

后來(lái),我查日志和數(shù)據(jù)庫(kù)發(fā)現(xiàn):有幾個(gè)商戶的訂單量特別大,剛好這幾個(gè)商戶被分到同一個(gè) partition,使得該 partition 的消息量比其他 partition 要多很多。

這時(shí)我們才意識(shí)到,發(fā)消息時(shí)按商戶編號(hào)路由 partition 的規(guī)則不合理。可能會(huì)導(dǎo)致有些 partition 消息太多消費(fèi)者處理不過(guò)來(lái),而有些 partition 卻因?yàn)橄⑻伲M(fèi)者出現(xiàn)空閑的情況。

為了避免出現(xiàn)這種分配不均勻的情況,我們需要對(duì)發(fā)消息的路由規(guī)則做一下調(diào)整。

我們思考了一下,用訂單號(hào)做路由相對(duì)更均勻,不會(huì)出現(xiàn)單個(gè)訂單發(fā)消息次數(shù)特別多的情況。除非是遇到某個(gè)人一直加菜的情況,但是加菜是需要花錢的,所以其實(shí)同一個(gè)訂單的消息數(shù)量并不多。

調(diào)整后按訂單號(hào)路由到不同的 partition,同一個(gè)訂單號(hào)的消息,每次到發(fā)到同一個(gè) partition。

調(diào)整后,消息積壓的問(wèn)題又有很長(zhǎng)一段時(shí)間都沒(méi)有再出現(xiàn)。我們的商戶數(shù)量在這段時(shí)間,增長(zhǎng)的非常快,越來(lái)越多了。

2.3 批量操作引起的連鎖反應(yīng)

在高并發(fā)的場(chǎng)景中,消息積壓?jiǎn)栴}可以說(shuō)如影隨形,真的沒(méi)辦法從根本上解決。表面上看已經(jīng)解決了,但后面不知道什么時(shí)候就會(huì)冒出一次。

比如這次。

有天下午,產(chǎn)品過(guò)來(lái)說(shuō):“有幾個(gè)商戶投訴過(guò)來(lái)了,他們說(shuō)菜品有延遲,快查一下原因”。

這次問(wèn)題出現(xiàn)得有點(diǎn)奇怪。

為什么這么說(shuō)?

首先這個(gè)時(shí)間點(diǎn)就有點(diǎn)奇怪,平常出問(wèn)題,不都是中午或者晚上用餐高峰期嗎?怎么這次問(wèn)題出現(xiàn)在下午?

根據(jù)以往積累的經(jīng)驗(yàn),我直接看了 Kafka 的 topic 的數(shù)據(jù),果然上面消息有積壓。但這次每個(gè) partition 都積壓了十幾萬(wàn)的消息沒(méi)有消費(fèi),比以往加壓的消息數(shù)量增加了幾百倍。這次消息積壓得極不尋常。

我趕緊查服務(wù)監(jiān)控看看消費(fèi)者掛了沒(méi),還好沒(méi)掛。又查服務(wù)日志沒(méi)有發(fā)現(xiàn)異常。這時(shí)我有點(diǎn)迷茫,碰運(yùn)氣問(wèn)了問(wèn)訂單組下午發(fā)生了什么事情沒(méi)?他們說(shuō)下午有個(gè)促銷活動(dòng),跑了一個(gè) Job 批量更新過(guò)有些商戶的訂單信息。

這時(shí),我一下子如夢(mèng)初醒:是他們?cè)?Job 中批量發(fā)消息導(dǎo)致的問(wèn)題。怎么沒(méi)有通知我們呢?實(shí)在太坑了。

雖說(shuō)知道問(wèn)題的原因了,倒是眼前積壓的這十幾萬(wàn)的消息該如何處理呢?

此時(shí),如果直接調(diào)大 partition 數(shù)量是不行的,歷史消息已經(jīng)存儲(chǔ)到4個(gè)固定的 partition,只有新增的消息才會(huì)到新的 partition。我們重點(diǎn)需要處理的是已有的 partition。

直接加服務(wù)節(jié)點(diǎn)也不行,因?yàn)?Kafka 允許同組的多個(gè) partition 被一個(gè) consumer 消費(fèi),但不允許一個(gè) partition 被同組的多個(gè) consumer 消費(fèi),可能會(huì)造成資源浪費(fèi)。

看來(lái)只有用多線程處理了。

為了緊急解決問(wèn)題,我改成了用線程池處理消息,核心線程和最大線程數(shù)都配置成了 50。

調(diào)整之后,果然,消息積壓數(shù)量不斷減少。

但此時(shí)有個(gè)更嚴(yán)重的問(wèn)題出現(xiàn):我收到了報(bào)警郵件,有兩個(gè)訂單系統(tǒng)的節(jié)點(diǎn)宕機(jī)了。

不久,訂單組的同事過(guò)來(lái)找我說(shuō),我們系統(tǒng)調(diào)用他們訂單查詢接口的并發(fā)量突增,超過(guò)了預(yù)計(jì)的好幾倍,導(dǎo)致有 2 個(gè)服務(wù)節(jié)點(diǎn)掛了。他們把查詢功能單獨(dú)整成了一個(gè)服務(wù),部署了 6 個(gè)節(jié)點(diǎn),掛了 2 個(gè)節(jié)點(diǎn)。再不處理,另外 4 個(gè)節(jié)點(diǎn)也會(huì)掛。訂單服務(wù)可以說(shuō)是公司最核心的服務(wù),它掛了公司損失會(huì)很大,情況萬(wàn)分緊急。

為了解決這個(gè)問(wèn)題,只能先把線程數(shù)調(diào)小。

幸好,線程數(shù)是可以通過(guò) ZooKeeper 動(dòng)態(tài)調(diào)整的。我把核心線程數(shù)調(diào)成了 8 個(gè),核心線程數(shù)改成了 10 個(gè)。

后面,運(yùn)維把訂單服務(wù)掛的 2 個(gè)節(jié)點(diǎn)重啟后恢復(fù)正常了。以防萬(wàn)一,再多加了 2 個(gè)節(jié)點(diǎn)。為了確保訂單服務(wù)不會(huì)出現(xiàn)問(wèn)題,就保持目前的消費(fèi)速度,后廚顯示系統(tǒng)的消息積壓?jiǎn)栴},1 小時(shí)候后也恢復(fù)正常了。

后來(lái),我們開(kāi)了一次復(fù)盤會(huì),得出的結(jié)論是:

訂單系統(tǒng)的批量操作一定提前通知下游系統(tǒng)團(tuán)隊(duì);

下游系統(tǒng)團(tuán)隊(duì)多線程調(diào)用訂單查詢接口一定要做壓測(cè);

這次給訂單查詢服務(wù)敲響了警鐘。它作為公司的核心服務(wù),應(yīng)對(duì)高并發(fā)場(chǎng)景做的不夠好,需要做優(yōu)化;

對(duì)消息積壓情況加監(jiān)控。

順便說(shuō)一下,對(duì)于要求嚴(yán)格保證消息順序的場(chǎng)景,可以將線程池改成多個(gè)隊(duì)列,每個(gè)隊(duì)列用單線程處理。

2.4 表過(guò)大

為了防止后面再次出現(xiàn)消息積壓?jiǎn)栴},消費(fèi)者后面就一直用多線程處理消息。

但有天中午我們還是收到很多報(bào)警郵件,提醒我們 Kafka 的 topic 消息有積壓。我們正在查原因,此時(shí)產(chǎn)品跑過(guò)來(lái)說(shuō):“又有商戶投訴說(shuō)菜品有延遲,趕緊看看”。

這次她看起來(lái)有些不耐煩,確實(shí)優(yōu)化了很多次還是出現(xiàn)了同樣的問(wèn)題。

在外行看來(lái):為什么同一個(gè)問(wèn)題一直解決不了?

其實(shí)技術(shù)心里的苦他們是不知道的。

表面上問(wèn)題的癥狀是一樣的,都是出現(xiàn)了菜品延遲。他們知道的是因?yàn)橄⒎e壓導(dǎo)致的,但是他們不知道深層次的原因。導(dǎo)致消息積壓的原因其實(shí)有很多種,這也許是使用消息中間件的通病吧。

我沉默不語(yǔ),只能硬著頭皮定位原因了。

后來(lái)我查日志發(fā)現(xiàn)消費(fèi)者消費(fèi)一條消息的耗時(shí)長(zhǎng)達(dá) 2 秒。以前是 500 毫秒,現(xiàn)在怎么會(huì)變成 2 秒呢?

奇怪了,消費(fèi)者的代碼也沒(méi)有做大的調(diào)整,為什么會(huì)出現(xiàn)這種情況呢?

查了一下線上菜品表,單表數(shù)據(jù)量竟然到了幾千萬(wàn),其他的劃菜表也是一樣,現(xiàn)在單表保存的數(shù)據(jù)太多了。

我們組梳理了一下業(yè)務(wù),其實(shí)菜品在客戶端只展示最近 3 天的即可。

這就好辦了,我們服務(wù)端存著多余的數(shù)據(jù),不如把表中多余的數(shù)據(jù)歸檔。于是 DBA 幫我們把數(shù)據(jù)做了歸檔,只保留最近 7 天的數(shù)據(jù)。

如此調(diào)整后,消息積壓?jiǎn)栴}被解決了,又恢復(fù)了往日的平靜。

3. 主鍵沖突

別高興得太早了,還有其他的問(wèn)題。比如報(bào)警郵件經(jīng)常報(bào)出數(shù)據(jù)庫(kù)異常:Duplicate entry ‘6’ for key ‘PRIMARY’,說(shuō)主鍵沖突。

出現(xiàn)這種問(wèn)題一般是由于有兩個(gè)以上相同主鍵的 SQL,同時(shí)插入數(shù)據(jù),第一個(gè)插入成功后,第二個(gè)插入的時(shí)候會(huì)報(bào)主鍵沖突。表的主鍵是唯一的,不允許重復(fù)。

我仔細(xì)檢查了代碼,發(fā)現(xiàn)代碼邏輯會(huì)先根據(jù)主鍵從表中查詢訂單是否存在,如果存在則更新?tīng)顟B(tài),不存在才插入數(shù)據(jù),沒(méi)得問(wèn)題。

這種判斷在并發(fā)量不大時(shí),是有用的。但是如果在高并發(fā)的場(chǎng)景下,兩個(gè)請(qǐng)求同一時(shí)刻都查到訂單不存在,一個(gè)請(qǐng)求先插入數(shù)據(jù),另一個(gè)請(qǐng)求再插入數(shù)據(jù)時(shí)就會(huì)出現(xiàn)主鍵沖突的異常。

解決這個(gè)問(wèn)題最常規(guī)的做法是:加鎖。

我剛開(kāi)始也是這樣想的,加數(shù)據(jù)庫(kù)悲觀鎖肯定是不行的,太影響性能。加數(shù)據(jù)庫(kù)樂(lè)觀鎖,基于版本號(hào)判斷,一般用于更新操作,像這種插入操作基本上不會(huì)用。

剩下的只能用分布式鎖了,我們系統(tǒng)在用 Redis,可以加基于 Redis 的分布式鎖,鎖定訂單號(hào)。

但后面仔細(xì)思考了一下:

加分布式鎖也可能會(huì)影響消費(fèi)者的消息處理速度;

消費(fèi)者依賴于 Redis,如果 Redis 出現(xiàn)網(wǎng)絡(luò)超時(shí),我們的服務(wù)就悲劇了。

所以,我也不打算用分布式鎖。

而是選擇使用 MySQL 的 INSERT INTO 。。.ON DUPLICATE KEY UPDATE 語(yǔ)法:

INSERTINTOtable (column_list)VALUES (value_list)ONDUPLICATEKEYUPDATEc1 = v1,c2 = v2,。。.;

它會(huì)先嘗試把數(shù)據(jù)插入表,如果主鍵沖突的話那么更新字段。

把以前的 insert 語(yǔ)句改造之后,就沒(méi)再出現(xiàn)過(guò)主鍵沖突問(wèn)題。

4. 數(shù)據(jù)庫(kù)主從延遲

不久之后的某天,又收到商戶投訴說(shuō)下單后,在劃菜客戶端上看得到訂單,但是看到的菜品不全,有時(shí)甚至訂單和菜品數(shù)據(jù)都看不到。

這個(gè)問(wèn)題跟以往的都不一樣,根據(jù)以往的經(jīng)驗(yàn)先看 Kafka 的 topic 中消息有沒(méi)有積壓,但這次并沒(méi)有積壓。

再查了服務(wù)日志,發(fā)現(xiàn)訂單系統(tǒng)接口返回的數(shù)據(jù)有些為空,有些只返回了訂單數(shù)據(jù),沒(méi)返回菜品數(shù)據(jù)。

這就非常奇怪了,我直接過(guò)去找訂單組的同事。他們仔細(xì)排查服務(wù),沒(méi)有發(fā)現(xiàn)問(wèn)題。這時(shí)我們不約而同的想到,會(huì)不會(huì)是數(shù)據(jù)庫(kù)出問(wèn)題了,一起去找 DBA。果然 DBA發(fā)現(xiàn)數(shù)據(jù)庫(kù)的主庫(kù)同步數(shù)據(jù)到從庫(kù),由于網(wǎng)絡(luò)原因偶爾有延遲,有時(shí)延遲有 3 秒。

如果我們的業(yè)務(wù)流程從發(fā)消息到消費(fèi)消息耗時(shí)小于 3 秒,調(diào)用訂單詳情查詢接口時(shí),可能會(huì)查不到數(shù)據(jù),或者查到的不是最新的數(shù)據(jù)。

這個(gè)問(wèn)題非常嚴(yán)重,會(huì)導(dǎo)致直接我們的數(shù)據(jù)錯(cuò)誤。

為了解決這個(gè)問(wèn)題,我們也加了重試機(jī)制。調(diào)用接口查詢數(shù)據(jù)時(shí),如果返回?cái)?shù)據(jù)為空,或者只返回了訂單沒(méi)有菜品,則加入重試表。

調(diào)整后,商戶投訴的問(wèn)題被解決了。

5. 重復(fù)消費(fèi)

Kafka消費(fèi)消息時(shí)支持三種模式:

at most once 模式:最多一次。保證每一條消息 commit 成功之后,再進(jìn)行消費(fèi)處理。消息可能會(huì)丟失,但不會(huì)重復(fù);

at least once 模式:至少一次。保證每一條消息處理成功之后,再進(jìn)行 commit。消息不會(huì)丟失,但可能會(huì)重復(fù);

exactly once 模式:精確傳遞一次。將 offset 作為唯一 id 與消息同時(shí)處理,并且保證處理的原子性。消息只會(huì)處理一次,不丟失也不會(huì)重復(fù)。但這種方式很難做到。

Kafka 默認(rèn)的模式是 at least once,但這種模式可能會(huì)產(chǎn)生重復(fù)消費(fèi)的問(wèn)題。所以我們的業(yè)務(wù)邏輯必須做冪等設(shè)計(jì)。

而我們的業(yè)務(wù)場(chǎng)景保存數(shù)據(jù)時(shí)使用了 INSERT INTO 。。.ON DUPLICATE KEY UPDATE 語(yǔ)法,不存在時(shí)插入,存在時(shí)更新,是天然支持冪等性的。

6. 多環(huán)境消費(fèi)問(wèn)題

我們當(dāng)時(shí)線上環(huán)境分為:pre(預(yù)發(fā)布環(huán)境)和 prod(生產(chǎn)環(huán)境),兩個(gè)環(huán)境共用同一個(gè)數(shù)據(jù)庫(kù),并且共用同一個(gè) Kafka 集群。

需要注意的是,在配置 Kafka 的 topic 的時(shí)候,要加前綴用于區(qū)分不同環(huán)境。pre環(huán)境的以 pre_ 開(kāi)頭,比如 pre_order。生產(chǎn)環(huán)境以 prod_開(kāi)頭,比如 prod_order,防止消息在不同環(huán)境中串了。

但有次運(yùn)維在 pre 環(huán)境切換節(jié)點(diǎn),配置 topic 的時(shí)候,錯(cuò)誤地配成了 prod 的 topic。剛好那天我們有新功能上 pre 環(huán)境,結(jié)果悲劇了:prod 的有些消息被 pre 環(huán)境的 consumer 消費(fèi)了。而由于消息體做了調(diào)整,導(dǎo)致 pre 環(huán)境的 consumer 處理消息一直失敗。

其結(jié)果是生產(chǎn)環(huán)境丟了部分消息。不過(guò)還好,最后生產(chǎn)環(huán)境消費(fèi)者通過(guò)重 置offset,重新讀取了那一部分消息解決了問(wèn)題,沒(méi)有造成太大損失。

后記

除了上述問(wèn)題之外,我還遇到過(guò):

Kafka 的 consumer 使用自動(dòng)確認(rèn)機(jī)制,導(dǎo)致 CPU 使用率 100%;

Kafka 集群中的一個(gè) broker 節(jié)點(diǎn)掛了,重啟后又一直掛。

這兩個(gè)問(wèn)題說(shuō)起來(lái)有些復(fù)雜,我就不一一列舉了。非常感謝那兩年使用消息中間件 Kafka 的經(jīng)歷,雖說(shuō)遇到過(guò)挺多問(wèn)題,踩了很多坑,走了很多彎路,但是實(shí)打?qū)嵉淖屛曳e累了很多寶貴的經(jīng)驗(yàn),快速成長(zhǎng)了。

其實(shí) Kafka 是一個(gè)非常優(yōu)秀的消息中間件,我所遇到的絕大多數(shù)問(wèn)題都并非 Kafka 自身的問(wèn)題(除了 CPU 使用率 100% 是它的一個(gè) bug 導(dǎo)致的之外)。

編輯:jq

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • kafka
    +關(guān)注

    關(guān)注

    0

    文章

    51

    瀏覽量

    5214

原文標(biāo)題:被坑慘了!盤點(diǎn) Kafka 一些非比尋常的坑

文章出處:【微信號(hào):LinuxHub,微信公眾號(hào):Linux愛(ài)好者】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    超詳細(xì)“零”基礎(chǔ)kafka入門篇

    1、認(rèn)識(shí)kafka 1.1 kafka簡(jiǎn)介 Kafka?是個(gè)分布式流媒體平臺(tái) kafka官網(wǎng):http://
    的頭像 發(fā)表于 12-18 09:50 ?153次閱讀
    超詳細(xì)“零”基礎(chǔ)<b class='flag-5'>kafka</b>入門篇

    FOC電路學(xué)習(xí)路上的一些硬件

    記錄下驅(qū)動(dòng)直流無(wú)刷電機(jī)走過(guò)的。我是和是室友起在玩FOC,電路方面也是借鑒了他的。我倆共同的個(gè)心得就是,電路這個(gè)東西直接抄要么你就要原封不動(dòng)的復(fù)刻下來(lái),要么你就要搞懂電路中的每個(gè)
    的頭像 發(fā)表于 12-07 10:14 ?189次閱讀
    FOC電路學(xué)習(xí)路上的<b class='flag-5'>一些</b>硬件<b class='flag-5'>坑</b>

    一些常見(jiàn)的動(dòng)態(tài)電路

    無(wú)論是模電還是數(shù)電,理論知識(shí)相對(duì)來(lái)說(shuō)還是比較枯燥,各種電路原理理解清楚不算容易,換種生動(dòng)形象的方式或許會(huì)增加一些趣味性,也更容易理解這些知識(shí)。下面整理了一些常見(jiàn)的電路,以動(dòng)態(tài)圖形的方式展示。 整流
    的頭像 發(fā)表于 11-16 09:26 ?320次閱讀
    <b class='flag-5'>一些</b>常見(jiàn)的動(dòng)態(tài)電路

    分享一些常見(jiàn)的電路

    理解模電和數(shù)電的電路原理對(duì)于初學(xué)者來(lái)說(shuō)可能比較困難,但通過(guò)一些生動(dòng)的教學(xué)方法和資源,可以有效地提高學(xué)習(xí)興趣和理解能力。 下面整理了一些常見(jiàn)的電路,以動(dòng)態(tài)圖形的方式展示。 整流電路 單相橋式整流
    的頭像 發(fā)表于 11-13 09:28 ?284次閱讀
    分享<b class='flag-5'>一些</b>常見(jiàn)的電路

    在學(xué)習(xí)go語(yǔ)言的過(guò)程踩過(guò)的

    作為個(gè)5年的phper,這兩年公司和個(gè)人都在順應(yīng)技術(shù)趨勢(shì),新項(xiàng)目慢慢從php轉(zhuǎn)向了go語(yǔ)言,從2021年到現(xiàn)在,筆者手上也先后開(kāi)發(fā)了兩個(gè)go項(xiàng)目。在學(xué)習(xí)go語(yǔ)言的過(guò)程中也學(xué)習(xí)并總結(jié)了一些相關(guān)的東西,這篇文章就分享下自己踩過(guò)的一些
    的頭像 發(fā)表于 11-11 09:22 ?159次閱讀

    Kafka高性能背后的技術(shù)原理

    Kafka款性能非常優(yōu)秀的消息隊(duì)列,每秒處理的消息體量可以達(dá)到千萬(wàn)級(jí)別。
    的頭像 發(fā)表于 10-23 09:37 ?315次閱讀
    <b class='flag-5'>Kafka</b>高性能背后的技術(shù)原理

    LED驅(qū)動(dòng)器應(yīng)用的一些指南和技巧

    電子發(fā)燒友網(wǎng)站提供《LED驅(qū)動(dòng)器應(yīng)用的一些指南和技巧.pdf》資料免費(fèi)下載
    發(fā)表于 09-25 11:35 ?0次下載
    LED驅(qū)動(dòng)器應(yīng)用的<b class='flag-5'>一些</b>指南和技巧

    非比率式磁流傳感器的精密設(shè)計(jì)

    電子發(fā)燒友網(wǎng)站提供《帶非比率式磁流傳感器的精密設(shè)計(jì).pdf》資料免費(fèi)下載
    發(fā)表于 09-23 12:37 ?0次下載
    帶<b class='flag-5'>非比</b>率式磁流傳感器的精密設(shè)計(jì)

    咨詢一些關(guān)于LED燈具的問(wèn)題

    各位大佬,咨詢一些關(guān)于LED燈具的問(wèn)題 120W的吸頂燈,用的非隔離式電源,用不到1年,燈具就會(huì)閃爍、頻閃或不亮,主要是什么原因造成的?是不是驅(qū)動(dòng)芯片太差?
    發(fā)表于 07-02 22:33

    面試官:Kafka會(huì)丟消息嗎?

    許多開(kāi)發(fā)人員普遍認(rèn)為,Kafka 的設(shè)計(jì)本身就能保證不會(huì)丟失消息。然而,Kafka 架構(gòu)和配置的細(xì)微差別會(huì)導(dǎo)致消息的丟失。我們需要了解它如何以及何時(shí)可能丟失消息,并防止此類情況的發(fā)生。
    的頭像 發(fā)表于 04-29 17:32 ?1013次閱讀
    面試官:<b class='flag-5'>Kafka</b>會(huì)丟消息嗎?

    細(xì)談SolidWorks教育版的一些基礎(chǔ)知識(shí)

    SolidWorks教育版是款廣泛應(yīng)用于工程設(shè)計(jì)和教育領(lǐng)域的三維建模軟件。它具備直觀易用的操作界面和強(qiáng)大的設(shè)計(jì)功能,為學(xué)生提供了個(gè)學(xué)習(xí)和實(shí)踐的平臺(tái)。在本文中,我們將詳細(xì)探討SolidWorks教育版的一些基礎(chǔ)知識(shí),幫助初學(xué)者
    的頭像 發(fā)表于 04-01 14:35 ?338次閱讀

    一些有關(guān)通信電路的資料?

    有關(guān)嵌入式之間DSP、ARM、FPGA三者之間和這三款芯片和外部電路之間通信的一些資料,比如說(shuō)芯片之間的并行通信和芯片和外部電路之間的串行通信,MODBUS、DP、CAN等,一些一些常用的通信協(xié)議的
    發(fā)表于 03-03 18:53

    Redis流與Kafka相比如何?

    我們先來(lái)看看Kafka的基本架構(gòu)。基本的數(shù)據(jù)結(jié)構(gòu)是主題。它是個(gè)按時(shí)間排序的記錄序列,只需追加。使用這種數(shù)據(jù)結(jié)構(gòu)的好處在Jay Kreps的經(jīng)典博文The Log中得到了很好的描述。
    的頭像 發(fā)表于 02-21 16:09 ?464次閱讀
    Redis流與<b class='flag-5'>Kafka</b>相比如何?

    一些無(wú)功補(bǔ)償裝置SVG的資料

    一些SVG電路原理和功能碼相關(guān)的技術(shù)說(shuō)明書,想了解一些SVG的工作原理和工作過(guò)程
    發(fā)表于 02-03 10:13

    kafka基本原理詳解

    今天浩道跟大家分享篇關(guān)于kafka相關(guān)原理的硬核干貨,可以說(shuō)即使你沒(méi)有接觸過(guò)kafka,也可以秒懂,起看看!
    的頭像 發(fā)表于 01-03 09:57 ?882次閱讀
    <b class='flag-5'>kafka</b>基本原理詳解
    主站蜘蛛池模板: 亚洲精品无码成人AAA片| brazzers欧美最新版视频| 风月宝鉴之淫乱英雄传 电影| xxxx俄罗斯1819| 精品一区二区三区AV天堂| 色精品极品国产在线视频| 2021精品高清卡1卡2卡3麻豆| 国产精品一区二区四区| 欧美亚洲精品一区二三区8V| 野花日本完整版在线观看免费高清 | 色拍拍噜噜噜久久蜜桃| 2020最新国产自产精品| 精品久久久亚洲精品中文字幕| 日日射夜夜干夜夜插在线播放| 97伦理97伦理2018最新| 久久国产精品永久网站| 亚洲狠狠97婷婷综合久久久久| 刺激一区仑乱| 欧美性受xxxx狂喷水| 中国老女人xxhd69| 激情女人花| 亚洲 综合 欧美在线 热| 国产成人久久精品激情| 日本久久中文字幕| 99久久国内精品成人免费| 久久亚洲精品AV成人无码| 亚洲人成在线播放网站岛国| 国产噜噜噜精品免费| 跳蛋按摩棒玉势PLAY高H| 处xxxx.88| 人妻免费久久久久久久了| 99在线免费观看| 欧美 亚洲综合在线一区| 2019天天射干网站| 久久视频在线视频| 在线自拍综合亚洲欧美| 久久99AV无色码人妻蜜柚| 亚洲视频在线观看免费| 护士们的母狗| 亚洲欧美另类无码专区| 京香在线观看|