開篇介紹
大家好,我是Java最全面試題庫的提褲姐,今天這篇是中間件面試題系列的第三篇,主要總結了Kafka相關的面試題;在后續(xù),會沿著第一篇開篇的知識線路一直總結下去,做到日更!如果我能做到百日百更,希望你也可以跟著百日百刷,一百天養(yǎng)成一個好習慣。
Kafka中的ISR、AR代表什么?ISR的伸縮指什么?
-
ISR:In-Sync Replicas 副本同步隊列 -
AR:Assigned Replicas 所有副本
ISR是由leader維護,follower從leader同步數(shù)據(jù)有一些延遲(包括延遲時間replica.lag.time.max.ms和延遲條數(shù)replica.lag.max.messages兩個維度,當前最新的版本0.10.x中只支持replica.lag.time.max.ms這個維度),任意一個超過閾值都會把follower剔除出ISR,存入OSR(Outof-Sync Replicas)列表,新加入的follower也會先存放在OSR中。
AR=ISR+OSR。
kafka中的broker 是干什么的?
broker 是消息的代理,
Producers往Brokers里面的指定Topic中寫消息,Consumers從Brokers里面拉取指定Topic的消息,然后進行業(yè)務處理,broker在中間起到一個代理保存消息的中轉站。
kafka中的 zookeeper 起到什么作用?
zookeeper 是一個分布式的協(xié)調組件,早期版本的kafka用zk做meta信息存儲,consumer的消費狀態(tài),group的管理以及 offset的值。
考慮到zk本身的一些因素以及整個架構較大概率存在單點問題,新版本中逐漸弱化了zookeeper的作用。新的consumer使用了kafka內部的group coordination協(xié)議,也減少了對zookeeper的依賴。
kafka follower如何與leader同步數(shù)據(jù)?
Kafka的復制機制既不是完全的同步復制,也不是單純的異步復制。
完全同步復制要求All Alive Follower都復制完,這條消息才會被認為commit,這種復制方式極大的影響了吞吐率。
異步復制方式下,F(xiàn)ollower異步的從Leader復制數(shù)據(jù),數(shù)據(jù)只要被Leader寫入log就被認為已經(jīng)commit,這種情況下,如果leader掛掉,會丟失數(shù)據(jù);
kafka使用ISR的方式很好的均衡了確保數(shù)據(jù)不丟失以及吞吐率。Follower可以批量的從Leader復制數(shù)據(jù),而且Leader充分利用磁盤順序讀以及send file(zero copy)機制,這樣極大的提高復制性能,內部批量寫磁盤,大幅減少了Follower與Leader的消息量差。
kafka 為什么那么快?
- Cache Filesystem Cache PageCache緩存
-
順序寫:由于現(xiàn)代的操作系統(tǒng)提供了預讀和寫技術,磁盤的順序寫大多數(shù)情況下比隨機寫內存還要快。 -
Zero-copy:零拷技術減少拷貝次數(shù) -
Batching of Messages:批量量處理。合并小的請求,然后以流的方式進行交互,直頂網(wǎng)絡上限。 -
Pull 拉模式:使用拉模式進行消息的獲取消費,與消費端處理能力相符。
kafka producer如何優(yōu)化打入速度?
- 增加線程
- 提高
batch.size - 增加更多
producer實例 - 增加
partition數(shù) - 設置
acks=-1時,如果延遲增大:可以增大num.replica.fetchers(follower 同步數(shù)據(jù)的線程數(shù))來調解; - 跨數(shù)據(jù)中心的傳輸:增加
socket緩沖區(qū)設置以及OS tcp緩沖區(qū)設置。
kafka producer發(fā)送數(shù)據(jù),ack為0,1,-1分別是什么意思?
-
1(默認) 數(shù)據(jù)發(fā)送到Kafka后,經(jīng)過leader成功接收消息的的確認,就算是發(fā)送成功了。在這種情況下,如果leader宕機了,則會丟失數(shù)據(jù)。 -
0生產(chǎn)者將數(shù)據(jù)發(fā)送出去就不管了,不去等待任何返回。這種情況下數(shù)據(jù)傳輸效率最高,但是數(shù)據(jù)可靠性確是最低的。 -
-1producer需要等待ISR中的所有follower都確認接收到數(shù)據(jù)后才算一次發(fā)送完成,可靠性最高。當ISR中所有Replica都向Leader發(fā)送ACK時,leader才commit,這時候producer才能認為一個請求中的消息都commit了。
kafka的message格式是什么樣的?
一個Kafka的Message由一個固定長度的header和一個變長的消息體body組成
header部分由一個字節(jié)的
magic(文件格式)和四個字節(jié)的CRC32(用于判斷body消息體是否正常)構成。
當magic的值為1的時候,會在magic和crc32之間多一個字節(jié)的數(shù)據(jù):attributes(保存一些相關屬性,
比如是否壓縮、壓縮格式等等);如果magic的值為0,那么不存在attributes屬性body是由N個字節(jié)構成的一個消息體,包含了具體的
key/value消息
kafka中consumer group 是什么概念?
同樣是邏輯上的概念,是Kafka實現(xiàn)單播和廣播兩種消息模型的手段。
同一個topic的數(shù)據(jù),會廣播給不同的group;
同一個group中的worker,只有一個worker能拿到這個數(shù)據(jù)。
換句話說,對于同一個topic,每個group都可以拿到同樣的所有數(shù)據(jù),但是數(shù)據(jù)進入group后只能被其中的一個worker消費。group內的worker可以使用多線程或多進程來實現(xiàn),也可以將進程分散在多臺機器上,worker的數(shù)量通常不超過partition的數(shù)量,且二者最好保持整數(shù)倍關系,因為Kafka在設計時假定了一個partition只能被一個worker消費(同一group內)。
Kafka中的消息是否會丟失和重復消費?
消息發(fā)送
Kafka消息發(fā)送有兩種方式:同步(sync)和異步(async),
默認是同步方式,可通過producer.type屬性進行配置。
Kafka通過配置request.required.acks屬性來確認消息的生產(chǎn)
- 0---表示不進行消息接收是否成功的確認;
- 1---表示當Leader接收成功時確認;
- -1---表示Leader和Follower都接收成功時確認;
綜上所述,有6種消息生產(chǎn)的情況,消息丟失的場景:
- acks=0,不和Kafka集群進行消息接收確認,則當網(wǎng)絡異常、緩沖區(qū)滿了等情況時,消息可能丟失;
- acks=1、同步模式下,只有Leader確認接收成功后但掛掉了,副本沒有同步,數(shù)據(jù)可能丟失;
消息消費
Kafka消息消費有兩個consumer接口,Low-level API和High-level API:
- Low-level API:消費者自己維護offset等值,可以實現(xiàn)對Kafka的完全控制;
- High-level API:封裝了對parition和offset的管理,使用簡單;
如果使用高級接口High-level API,可能存在一個問題就是當消息消費者從集群中把消息取出來、并提交了新的消息offset值后,還沒來得及消費就掛掉了,那么下次再消費時之前沒消費成功的消息就“詭異”的消失了;
解決辦法:
針對消息丟失:同步模式下,確認機制設置為-1,即讓消息寫入Leader和Follower之后再確認消息發(fā)送成功;異步模式下,為防止緩沖區(qū)滿,可以在配置文件設置不限制阻塞超時時間,當緩沖區(qū)滿時讓生產(chǎn)者一直處于阻塞狀態(tài);
針對消息重復:將消息的唯一標識保存到外部介質中,每次消費時判斷是否處理過即可。
為什么Kafka不支持讀寫分離?
在 Kafka 中,生產(chǎn)者寫入消息、消費者讀取消息的操作都是與 leader 副本進行交互的,從 而實現(xiàn)的是一種主寫主讀的生產(chǎn)消費模型。
Kafka 并不支持主寫從讀,因為主寫從讀有 2 個很明 顯的缺點:
- 數(shù)據(jù)一致性問題。數(shù)據(jù)從主節(jié)點轉到從節(jié)點必然會有一個延時的時間窗口,這個時間 窗口會導致主從節(jié)點之間的數(shù)據(jù)不一致。某一時刻,在主節(jié)點和從節(jié)點中 A 數(shù)據(jù)的值都為 X, 之后將主節(jié)點中 A 的值修改為 Y,那么在這個變更通知到從節(jié)點之前,應用讀取從節(jié)點中的 A 數(shù)據(jù)的值并不為最新的 Y,由此便產(chǎn)生了數(shù)據(jù)不一致的問題。
-
延時問題。類似 Redis 這種組件,數(shù)據(jù)從寫入主節(jié)點到同步至從節(jié)點中的過程需要經(jīng)歷
網(wǎng)絡→主節(jié)點內存→網(wǎng)絡→從節(jié)點內存這幾個階段,整個過程會耗費一定的時間。而在 Kafka 中,主從同步會比 Redis 更加耗時,它需要經(jīng)歷網(wǎng)絡→主節(jié)點內存→主節(jié)點磁盤→網(wǎng)絡→從節(jié)點內存→從節(jié)點磁盤這幾個階段。對延時敏感的應用而言,主寫從讀的功能并不太適用。