無消息丟失配置怎么實(shí)現(xiàn)?
-
Kafka 只對“已提交”的消息(committed message)做有限度的持久化保證。
- 第一個核心要素是“已提交的消息”。
- 當(dāng) Kafka 的若干個 Broker 成功地接收到一條消息并寫入到日志文件后,它們會告訴生產(chǎn)者程序這條消息已成功提交。
- 可以選擇只要有一個 Broker 成功保存該消息就算是已提交,也可以是令所有 Broker 都成功保存該消息才算是已提交。
- 第二個核心要素就是“有限度的持久化保證”。
- Kafka 不可能保證在任何情況下都做到不丟失消息。
- Kafka 不丟消息是有前提條件的。假如你的消息保存在 N 個 Kafka Broker 上,那么這個前提條件就是這 N 個 Broker 中至少有 1 個存活。
- 第一個核心要素是“已提交的消息”。
消息丟失案例
案例 1:生產(chǎn)者程序丟失數(shù)據(jù)
- 目前 Kafka Producer 是異步發(fā)送消息的,也就是說如果你調(diào)用的是 producer.send(msg) 這個 API,那么它通常會立即返回,但此時你不能認(rèn)為消息發(fā)送已成功完成。
- 如果用這個方式,可能會有哪些因素導(dǎo)致消息沒有發(fā)送成功呢?
- 網(wǎng)絡(luò)抖動,導(dǎo)致消息壓根就沒有發(fā)送到 Broker 端;
- 消息本身不合格導(dǎo)致 Broker 拒絕接收(比如消息太大了,超過了 Broker 的承受能力)。
- 解決此問題的方法非常簡單:
- Producer 永遠(yuǎn)要使用帶有回調(diào)通知的發(fā)送 API,也就是說不要使用 producer.send(msg),而要使用 producer.send(msg, callback)。
案例 2:消費(fèi)者程序丟失數(shù)據(jù)
- Consumer 端丟失數(shù)據(jù)主要體現(xiàn)在 Consumer 端要消費(fèi)的消息不見了。
- Consumer 程序有個“位移”的概念,表示的是這個 Consumer 當(dāng)前消費(fèi)到的 Topic 分區(qū)的位置。
- 只要維持先消費(fèi)消息,再更新位移的順序即可。這樣就能最大限度地保證消息不丟失。這種處理方式可能帶來的問題是消息的重復(fù)處理。
- Consumer 程序有個“位移”的概念,表示的是這個 Consumer 當(dāng)前消費(fèi)到的 Topic 分區(qū)的位置。
- 還存在一種比較隱蔽的消息丟失場景。
- Consumer 程序從 Kafka 獲取到消息后開啟了多個線程異步處理消息,而 Consumer 程序自動地向前更新位移。
- 假如其中某個線程運(yùn)行失敗了,它負(fù)責(zé)的消息沒有被成功處理,但位移已經(jīng)被更新了,因此這條消息對于 Consumer 而言實(shí)際上是丟失了。
- 這里的關(guān)鍵在于 Consumer 自動提交位移,你沒有真正地確認(rèn)消息是否真的被消費(fèi)就“盲目”地更新了位移。
- 這個問題的解決方案也很簡單:如果是多線程異步處理消費(fèi)消息,Consumer 程序不要開啟自動提交位移,而是要應(yīng)用程序手動提交位移。
最佳實(shí)踐
- 不要使用 producer.send(msg),而要使用 producer.send(msg, callback)。記住,一定要使用帶有回調(diào)通知的 send 方法。
-
設(shè)置 acks = all。
- acks 是 Producer 的一個參數(shù),代表了你對“已提交”消息的定義。
- 如果設(shè)置成 all,則表明所有副本 Broker 都要接收到消息,該消息才算是“已提交”。
- 這是最高等級的“已提交”定義。
-
設(shè)置 retries 為一個較大的值。
- 這?的 retries 同樣是 Producer 的參數(shù),對應(yīng) Producer 自動重試。
- 當(dāng)出現(xiàn)網(wǎng)絡(luò)的瞬時抖動時,消息發(fā)送可能會失敗,此時配置了 retries > 0 的 Producer 能夠自動重試消息發(fā)送,避免消息丟失。
-
設(shè)置 unclean.leader.election.enable = false。
- 這是 Broker 端的參數(shù),它控制的是哪些 Broker 有資格競選分區(qū)的 Leader。
- 如果一個 Broker 落后原先的 Leader 太多,那么它一旦成為新的 Leader,必然會造成消息的丟失。
- 故一般都要將該參數(shù)設(shè)置成 false,即不允許這種情況的發(fā)生。
-
設(shè)置 replication.factor >= 3。
- 這也是 Broker 端的參數(shù)。
- 其實(shí)這里想表述的是,最好將消息多保存幾份,畢竟目前防止消息丟失的主要機(jī)制就是冗余。
-
設(shè)置 min.insync.replicas > 1。
- 這依然是 Broker 端參數(shù),控制的是消息至少要被寫入到多少個副本才算是“已提交”。
- 設(shè)置成大于 1 可以提升消息持久性。
- 在實(shí)際環(huán)境中千萬不要使用默認(rèn)值 1。
-
確保 replication.factor > min.insync.replicas。
- 如果兩者相等,那么只要有一個副本掛機(jī),整個分區(qū)就無法正常工作了。
- 我們不僅要改善消息的持久性,防止數(shù)據(jù)丟失,還要在不降低可用性的基礎(chǔ)上完成。
- 推薦設(shè)置成 replication.factor = min.insync.replicas + 1。
-
確保消息消費(fèi)完成再提交。
- Consumer 端有個參數(shù) enable.auto.commit,最好把它設(shè)置成 false,并采用手動提交位移的方式。
文章來源地址http://www.zghlxwxcb.cn/news/detail-602083.html
文章來源:http://www.zghlxwxcb.cn/news/detail-602083.html
到了這里,關(guān)于《kafka 核心技術(shù)與實(shí)戰(zhàn)》課程學(xué)習(xí)筆記(八)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!