1. 副本機(jī)制
在分布式系統(tǒng)中椿每,為了提高可靠性捶闸,最常用、最有效的策略是“副本機(jī)制”拖刃,Kafka 也不例外。Kafka 為每個(gè) Partition 維護(hù)了一個(gè) AR(Assigned Replicas)列表贪绘,由 ISR(In-Sync Replicas兑牡,與 Leader 數(shù)據(jù)同步的 Replica)和 OSR(Outof-Sync Replicas,與 Leader 數(shù)據(jù)不同步的 Replica)組成税灌。初始狀態(tài)下均函,所有的 Replica 都在 ISR 中,但在 Kafka 工作過程中菱涤,由于各種問題(網(wǎng)絡(luò)苞也、磁盤、內(nèi)存)可能導(dǎo)致部分 Replica 的同步速度慢于參數(shù) replica.lag.time.max.ms
指定的閾值粘秆,一旦出現(xiàn)這種情況如迟,這部分 Replica 會被移出 ISR,降級至 OSR 中攻走。
關(guān)于參數(shù) replica.lag.time.max.ms
數(shù)據(jù)類型為 Long殷勘,默認(rèn)值為 10000,重要性為 High昔搂,官方解釋如下:
If a follower hasn't sent any fetch requests or hasn't consumed up to the leaders log end offset for at least this time, the leader will remove the follower from ISR.
副本機(jī)制如何作用玲销?
Producer 指定 Topic 向 Broker 發(fā)送消息,經(jīng)過內(nèi)部處理(如負(fù)載均衡等)后寫入某 Partition 的 Leader摘符,Leader 收到消息數(shù)據(jù)后并不會立即回應(yīng) Producer贤斜,而是等待 ISR 列表中所有的 Replica 同步數(shù)據(jù)完成策吠,之后才向 Producer 返回成功消息。這是不是與 Raft 算法有點(diǎn)類似瘩绒?
基于上述分析猴抹,不難理解,只要保證 ISR 中的 Replica 數(shù)量大于 2(ISR 包括 Leader)草讶,即便出現(xiàn) Leader 突然故障下線的情況洽糟,也能保證消息不丟失(因?yàn)?ISR 中的 Replica 與 Leader 保持同步)。當(dāng)然堕战,凡事過猶不及坤溃,ISR 中 Replica 的數(shù)量不宜過多,否則會降低 Kafka 的吞吐性能嘱丢。
補(bǔ)充一點(diǎn)薪介,OSR 內(nèi)的 Replica 是否同步了 Leader 的數(shù)據(jù)不影響數(shù)據(jù)是否提交成功,這些 Replica 會不斷從 Leader 中同步數(shù)據(jù)越驻。至于同步的進(jìn)度并不重要汁政,不過,運(yùn)維人員應(yīng)密切關(guān)注 Replica 從 ISR 中降級轉(zhuǎn)入 OSR 的情況缀旁,并及時(shí)排查故障记劈,使其盡快回到 ISR 中,以維持 ISR 中 Replica 的數(shù)量處于合理狀態(tài)并巍,同時(shí)降低集群宕機(jī)的風(fēng)險(xiǎn)目木。
2. 截?cái)鄼C(jī)制
在第 12 課中,我們介紹了 LEO 和 HW 在正常情況下的流轉(zhuǎn)過程懊渡,那遇到異常情況又會怎樣呢刽射?
如果出現(xiàn) Leader 故障下線的情況,就需要從所有的 Follower 中選舉新的 Leader剃执,以便繼續(xù)提供服務(wù)誓禁。為了保證一致性,通常只能從 ISR 列表中選取新的 Leader (上面已經(jīng)介紹肾档,ISR 列表中的 Follower 與原 Leader 保持同步)摹恰,因此,無論 ISR 中哪個(gè) Follower 被選為新的 Leader怒见,它都知道 HW 之前的數(shù)據(jù)戒祠,可以保證在切換了 Leader 后,Consumer 可以繼續(xù)“看到”之前已經(jīng)由 Producer 提交的數(shù)據(jù)速种。
如下圖所示姜盈,如果 Leader 宕機(jī),F(xiàn)ollower1 被選為新的 Leader配阵,而新 Leader (原 Follower1 )并沒有完全同步之前 Leader 的所有數(shù)據(jù)(少了一個(gè)消息 6)馏颂,之后示血,新 Leader 又繼續(xù)接受了新的數(shù)據(jù),此時(shí)救拉,原本宕機(jī)的 Leader 經(jīng)修復(fù)后重新上線难审,它將發(fā)現(xiàn)新 Leader 中的數(shù)據(jù)和自己持有的數(shù)據(jù)不一致,怎么辦呢亿絮?
為了保證一致性告喊,必須有一方妥協(xié),顯然舊的 Leader 優(yōu)先級較低派昧,因此黔姜, 它會將自己的數(shù)據(jù)截?cái)嗟藉礄C(jī)之前的 HW 位置(HW 之前的數(shù)據(jù),與 Leader 一定是相同的)蒂萎,然后同步新 Leader 的數(shù)據(jù)秆吵。這便是所謂的 “截?cái)鄼C(jī)制”。
3. 消息生產(chǎn)的可靠性
3.1 消息可能重復(fù)生產(chǎn)
在第 12 課 2.4 小節(jié)中五慈,我們介紹了消息生產(chǎn)過程中保證數(shù)據(jù)可靠性的策略纳寂。該策略雖然可以保障消息不丟失,但無法避免出現(xiàn)重復(fù)消息泻拦。例如毙芜,生產(chǎn)者發(fā)送數(shù)據(jù)給 Leader,Leader 同步數(shù)據(jù)給 ISR 中的 Follower争拐,同步到一半 Leader 時(shí)宕機(jī)腋粥,此時(shí)選出新的 Leader,它可能具有部分此次提交的數(shù)據(jù)陆错,而生產(chǎn)者收到發(fā)送失敗響應(yīng)后將重發(fā)數(shù)據(jù),新的 Leader 接受數(shù)據(jù)則數(shù)據(jù)重復(fù)金赦。因此 Kafka 只支持“At Most Once”和“At Least Once”音瓷,而不支持“Exactly Once”,消息去重需在具體的業(yè)務(wù)中實(shí)現(xiàn)夹抗。
- At Most Once:消息可能會丟绳慎,但絕不會重復(fù)傳輸;
- At Least Once:消息絕不會丟漠烧,但可能會重復(fù)傳輸杏愤;
- Exactly once:每條消息肯定會被傳輸一次且僅傳輸一次。
3.2 配置示例
綜上所述已脓,對高可靠性有要求的應(yīng)用場景中珊楼,生產(chǎn)者的配置示例如下。
Broker 配置:
default.replication.factor=3
min.insync.replicas=2
Producer 配置:
roperties props = new Properties();
props.put("bootstrap.servers", "100.120.130.170:9092,100.120.130.171:9092, 100.120.130.172:9092");
props.put("acks", "all"); //保證高可靠性度液,設(shè)置成"all"或者"-1"
props.put("retries", 3); //重試次數(shù)閾值厕宗,這里設(shè)置為3
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer"); //這里是key的序列化類
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");//這里是value的序列化類
Producer<String, String> producer = new KafkaProducer<String,String>(props);