書接上回意述。在寫完上一篇文章后浴栽,回想內(nèi)容時,其實還有疑問還沒有解開:消費組狀態(tài)從等待同步狀態(tài)轉(zhuǎn)換到準備再平衡狀態(tài)涎劈,會不會生成延遲對象广凸?
要解開以上的疑問,就得看看協(xié)調(diào)者是怎么處理消費者的同步組請求蛛枚。
協(xié)調(diào)者處理同步組請求
消費組的狀態(tài)進入等待同步后谅海,協(xié)調(diào)者就會發(fā)送加入組請求響應給所有的消費者(注意這個時候消費組中的所有消費者都發(fā)送了加入組請求,并協(xié)調(diào)者啟動了心跳機制對消費者進行監(jiān)控)蹦浦。收到加入組請求響應后扭吁,如果是非主消費者會立即發(fā)送同步組請求,協(xié)調(diào)者接收到非主消費者的同步組請求只會設置其對應的消費者元數(shù)據(jù)中的回調(diào)方法。主消費者還沒有發(fā)送同步組請求侥袜,就不會發(fā)送同步組響應給消費者蝌诡,只能將回調(diào)方法暫時存放到消費者元數(shù)據(jù)中。如果是主消費者枫吧,會馬上執(zhí)行分區(qū)分配算法浦旱,完成后會發(fā)送同步組請求到協(xié)調(diào)者。協(xié)調(diào)者在收到主消費者的同步組請求后九杂,這時就會發(fā)送同步組響應給發(fā)送了同步請求的消費者(注意這時有可能還有的消費者沒有發(fā)送同步組請求到協(xié)調(diào)者颁湖,這個消費者的同步回調(diào)方法對象就是為空,不會收到協(xié)調(diào)者的同步組請求響應)例隆。改變消費組的狀態(tài)為穩(wěn)定甥捺。
協(xié)調(diào)者在處理同步組請求時,重點分析從兩種狀態(tài)進入:準備再平衡和穩(wěn)定(如果消費組的狀態(tài)本來就是等待同步狀態(tài)镀层,這種狀態(tài)本身就在等消費者的同步請求)
準備再平衡狀態(tài)
從上一節(jié)的分析了解到镰禾,第一個消費者發(fā)送加入組請求時,消費組的狀態(tài)會變到等待同步鹿响,并且第一個消費者會作為主消費者執(zhí)行分區(qū)分配羡微。
當有第二個消費者作為新的消費者發(fā)送加入組請求,會將消費組的狀態(tài)改為準備再平衡惶我。當?shù)谝粋€消費者執(zhí)行完分區(qū)分配后(在這種情況下分區(qū)的分配其實是無效的妈倔,因為消費組里面又多了一個消費者)。會發(fā)送同步組請求到協(xié)調(diào)者绸贡,由于現(xiàn)在消費組處于準備再平衡狀態(tài)盯蝴,就不能接受第一個消費者的分區(qū)分配結果。這時需要返回一個錯誤信息給第一個消費者听怕,讓它重新發(fā)送加入組請求捧挺。
穩(wěn)定狀態(tài)
穩(wěn)定狀態(tài)下并不意味著消費組中的所有消費者都發(fā)送了同步組請求,但是都已經(jīng)發(fā)送了加入組請求尿瞭。協(xié)調(diào)者在沒有收到主消費者的同步組請求之前闽烙,收到的任何非主消費者的同步組請求都只會設置其消費者元數(shù)據(jù)中的回調(diào)方法。當收到主消費者的同步組請求后声搁,協(xié)調(diào)者會立即發(fā)送同步組響應給所有發(fā)了同步組請求的消費者黑竞,并之后更改消費組的狀態(tài)為穩(wěn)定狀態(tài)。在此之后的消費者發(fā)送同步組請求疏旨,協(xié)調(diào)者會直接發(fā)送同步組響應給消費者很魂,因為這時協(xié)調(diào)者已經(jīng)存了該消費者的分區(qū)分配信息。
消費組狀態(tài)轉(zhuǎn)換
再聊準備再平衡
一次再平衡的正常消費組的狀態(tài)變化過程是:穩(wěn)定-->準備再平衡-->等待同步-->穩(wěn)定檐涝。消費組從等待同步轉(zhuǎn)到準備再平衡遏匆,從穩(wěn)定轉(zhuǎn)到準備再平衡,只要是進入準備再平衡狀態(tài)都會創(chuàng)建一個延遲操作凡纳。協(xié)調(diào)者處理多個消費者的請求喊暖,并不會創(chuàng)建多個延遲的操作對象惫企,當遇到消費組中的一個消費者發(fā)送加入組請求把消費組的狀態(tài)改為準備再平衡,這時就會為消費組創(chuàng)建一個延遲操作對象陵叽,等消費組中其他的消費者發(fā)送加入組請求時,需要做的是去嘗試完成該延遲操作對象巩掺。等消費組中所有的消費者都發(fā)送加入組請求后,就完成該延遲操作對象胖替。更新消費組的狀態(tài)為等待同步研儒。
協(xié)調(diào)者處理同步組請求,如果是非主消費者發(fā)送同步組請求独令,它沒有帶分區(qū)分配結果,協(xié)調(diào)者在處理請求時只會更新消費者元數(shù)據(jù)的回調(diào)方法冲呢,結束流程。如果是主消費者發(fā)送的同步組請求敬拓,因為帶有分區(qū)分配結果裙戏,會將分區(qū)分配結果同步到內(nèi)部主題中,并設置消費者元數(shù)據(jù)的回調(diào)方法累榜,最后會調(diào)用每個發(fā)送同步組請求的消費者的回調(diào)方法壹罚,發(fā)送帶有分區(qū)結果的同步響應給消費者,改變消費組的狀態(tài)為穩(wěn)定渔嚷。
協(xié)調(diào)者在處理加入組請求和同步組請求稠曼,會對消費組元數(shù)據(jù)進行加鎖客年。只有協(xié)調(diào)者釋放了消費組元數(shù)據(jù)的鎖量瓜,才可以處理其他消費者的請求途乃。協(xié)調(diào)者處理同一個消費者的加入組請求和同步組請求這個順序是固定的。協(xié)調(diào)者在處理不同消費者的請求時耍共,會出現(xiàn)鎖等待,比如:協(xié)調(diào)者在處理第一個消費者的加入組請求杠纵,就不能同時處理其他消費者的加入組請求钩骇;協(xié)調(diào)者正在處理第一個消費者的同步組請求,就不能同時處理其他消費者的加入組請求和同步組請求(注意银亲,在協(xié)調(diào)者把主消費者的分區(qū)分配結果保存到內(nèi)部主題中時纽匙,這個時候是不需要操作消費組元數(shù)據(jù)的,此時會釋放鎖)哄辣。
協(xié)調(diào)者者處理不同事件力穗,會根據(jù)狀態(tài)機的狀態(tài)執(zhí)行不同的動作,而執(zhí)行動作又會間接影響狀態(tài)機的狀態(tài)当窗。
協(xié)調(diào)者處理加入組請求
協(xié)調(diào)者處理消費者的加入組請求崖面,根據(jù)消費組的不同狀態(tài)分別執(zhí)行不同的分支流程:
消費組狀態(tài)為準備再平衡
第一個消費者C1加入組,從穩(wěn)定到準備再平衡再到等待同步巫员;第二個消費者C2加入組,從等待同步到準備再平衡赶掖;這個情況下新的消費者C3和舊消費者C1都會向協(xié)調(diào)者發(fā)送加入組請求從準備再平衡狀態(tài)進去(C3是新加入,C1是重新加入)陪白。
新消費者先于舊消費者發(fā)送加入組
1膳灶,新消費者在舊消費者重新發(fā)送加入組之前,先發(fā)送了加入組請求序厉,對應創(chuàng)建消費者元數(shù)據(jù)聋迎,并加入組到消費組元數(shù)據(jù)中。
2霉晕,舊消費者重新發(fā)送加入組請求,對應會更新消費者元數(shù)據(jù)信息拄轻。
舊消費者先于新消費者發(fā)送加入組
協(xié)調(diào)者處理舊消費者的加入組伟葫,會完成延遲操作,并更改消費組狀態(tài)為等待同步斧抱。然后新消費者發(fā)送加入組請求就是從等待同步狀態(tài)進入渐溶,然后改變消費組狀態(tài)為準備再平衡,其他消費者重新發(fā)送加入組請求宪郊。
消費組狀態(tài)為等待同步
在等待同步狀態(tài)時拖陆,新消費者加入組和前面講的過程一樣。但是如果遇到舊消費者加入組就有點怪了乎串,因為正常情況下到了等待同步狀態(tài)時速警,消費組里面的消費者都發(fā)送了加入組后協(xié)調(diào)者才會完成延遲操作對象艰争,并更改狀態(tài)為等待同步桂对。但是如果消費者由于原因沒有收到加入組響應鸠匀,它就會重新發(fā)送加入組請求,這種情況下協(xié)調(diào)者處理已知的消費者的加入組請求時并不會更改消費組狀態(tài)宅此,也不會執(zhí)行新增或者更新消費者元數(shù)據(jù)的方法爬范,只需要直接返回加入組響應給此消費者。
消費組狀態(tài)為穩(wěn)定
如果消費者發(fā)送了加入組請求璧亮,但是沒有收到加入組請求的響應斥难,協(xié)調(diào)者的狀態(tài)會是等待同步;如果消費者發(fā)送了同步組請求群扶,但是沒有收到同步組請求的響應镀裤,協(xié)調(diào)者的狀態(tài)會是穩(wěn)定。協(xié)調(diào)者給每個消費者發(fā)送響應骆莹,并不保證每個消費者就一定能收到響應結果铃岔。如果消費者自己的問題,就需要重新發(fā)送請求毁习。
消費組達到穩(wěn)定狀態(tài)后,表示協(xié)調(diào)者處理了主消費者發(fā)送的同步組請求盏道,但并不意味著其他的消費者都發(fā)送了同步組請求载碌。
非主消費者發(fā)送了加入組請求衅枫,但沒有收到加入組響應弦撩,需要重新發(fā)送加入組請求论皆,協(xié)調(diào)者處理這個消費者重新發(fā)送的加入組請求時,因為現(xiàn)在消費組的狀態(tài)是穩(wěn)定狀態(tài)点晴,所以協(xié)調(diào)者會立即返回加入組請求的響應給消費者粒督。
步驟:
1,三個消費者發(fā)送加入組請求給協(xié)調(diào)者屠橄,消費者狀態(tài)從準備再平衡到等待同步仇矾。
2,協(xié)調(diào)者返回加入組響應給三個消費者贮匕,前兩個消費者收到了響應刻盐,第三個消費者沒有收到響應。
3敦锌,第二個消費者是普通消費者,收到加入組響應后颖变,立即發(fā)送同步請求听想,協(xié)調(diào)者處理請求只會設置其消費者元數(shù)據(jù)中的回調(diào)方法。
4衔峰,第一個消費者是主消費者,它完成了分區(qū)分配威彰,發(fā)送同步組請求穴肘,協(xié)調(diào)者改變消費組的狀態(tài)為穩(wěn)定。
5旺遮,協(xié)調(diào)者返回同步組響應給前兩個消費者盈咳,因為第三個消費者沒有收到加入組響應边翼,也就沒有發(fā)送同步組請求,所以沒有設置回調(diào)方法丈积。
6债鸡,第三個消費者沒有收到加入組響應,重新發(fā)送加入組請求唬滑。
7棺弊,協(xié)調(diào)者處理第三個消費者的加入組請求,消費組的狀態(tài)是穩(wěn)定稻艰,立即返回加入組響應侈净。
8,第三個消費者不是主消費者元扔,收到加入組響應夏伊,會立即發(fā)送同步組請求。
9咏连,協(xié)調(diào)者處理第三個消費者的同步組請求,消費組的狀態(tài)是穩(wěn)定祟滴,立即返回同步組響應垄懂。
以上是非主消費者沒有收到加入組響應,如果是主消費沒有收到加入組響應桶蛔。由于主消費者沒有收到加入組響應漫谷,它就不會執(zhí)行分區(qū)分配,也不會發(fā)送同步組請求碟婆。協(xié)調(diào)者也不會把消費組的狀態(tài)改為穩(wěn)定惕稻,依然是等待同步。只能等待主消費者重新的發(fā)送加入組請求公给。
步驟:
1锻煌,三個消費者發(fā)送加入組請求給協(xié)調(diào)者,消費者狀態(tài)從準備再平衡到等待同步匣沼。
2捂龄,協(xié)調(diào)者返回加入組響應給三個消費者,前兩個消費者收到了響應唇撬,第三個消費者沒有收到響應展融。
3,前兩個消費者是普通消費者扑浸,收到加入組響應后,立即發(fā)送同步請求础嫡,協(xié)調(diào)者處理請求只會設置其消費者元數(shù)據(jù)中的回調(diào)方法酝惧。
4,主消費者沒有收到加入組響應巫财,重新發(fā)送加入組請求哩陕。
5,協(xié)調(diào)者處理主消費者的加入組請求,消費組的狀態(tài)是等待同步并鸵,立即返回加入組響應扔涧。
6,主消費者收到加入組響應弯汰,執(zhí)行分區(qū)分配湖雹,并發(fā)送同步組請求。
7鸽嫂,協(xié)調(diào)者處理主消費者的同步組請求征讲,返回給所有消費者同步組響應,并改變消費組的狀態(tài)為穩(wěn)定癣籽。
協(xié)調(diào)者先改變消費組狀態(tài)為等待同步再發(fā)送加入組響應,而后是先返回同步組響應瓶籽,再改變消費組狀態(tài)為穩(wěn)定桑逝。為什么?
我們現(xiàn)在不防這樣來看看茬暇,如果協(xié)調(diào)者先發(fā)送加入組響應寡喝,再改變消費組的狀態(tài)為等待同步:在這樣的情況下预鬓,消費組的狀態(tài)是準備再平衡,能夠發(fā)送加入組響應就代表延遲操作可以完成格二,那么表示消費組里面的消費者都發(fā)送了加入組請求顶猜。如果此時新的一個消費者發(fā)送了加入組請求,現(xiàn)在的狀態(tài)本來就是準備再平衡滔吠,所以首先不會創(chuàng)建延遲操作挠日,再者會執(zhí)行新消費者元數(shù)據(jù)的創(chuàng)建和添加到消費組元數(shù)據(jù)中。這時消費組中就會多出一個消費者冬骚,收到加入組響應的主消費者再執(zhí)行分區(qū)分配是沒有意義的也是不對的郑原,并且更嚴重的是協(xié)調(diào)者并沒有辦法告知消費者,并且后面也會改變消費組的狀態(tài)為等待同步属愤,消費者也會發(fā)送同步組請求酸役。但是新的消費者收不到加入組響應,也就不會發(fā)送同步組請求贱呐。隨即消費組的狀態(tài)變?yōu)榱朔€(wěn)定奄薇。只有等到新的那個消費者發(fā)現(xiàn)還沒有收到加入組響應,重新發(fā)送加入組請求到協(xié)調(diào)者呵晚。又執(zhí)行一遍再平衡沫屡。這樣的情況就增加消費者和協(xié)調(diào)者之間網(wǎng)絡通信次數(shù)。所以協(xié)調(diào)者先改變消費組狀態(tài)為等待同步再發(fā)送加入組響應可以減少消費者和協(xié)調(diào)者之間的冗余通信金矛。
再來看看勺届,如果協(xié)調(diào)者先把消費組改為穩(wěn)定,再發(fā)送同步組響應給客戶端废睦,會發(fā)生什么?其實這個是要看協(xié)調(diào)者什么時候才會把消費組的狀態(tài)變?yōu)榉€(wěn)定奈应。協(xié)調(diào)者是在收到主消費者的同步組請求后,才會去更改消費組的狀態(tài)為穩(wěn)定肩榕。設想如果只有一個消費者的情況下惩妇,那么那個消費者就是主消費者歌殃,在這種情況下,是先修改狀態(tài)為穩(wěn)定氓皱,還是先發(fā)送同步組響應給客戶端都沒什么關系。那么如果存在多個消費者的情況下身隐,在沒有收到主消費者的同步組請求之前唯灵,先改狀態(tài)和先發(fā)送同步組響應都是無意義的。因為本身沒有收到主消費者的同步組請求垢揩,就沒有收到分區(qū)的分配結果搞监。只有收到了主消費者的同步組請求后,就可以發(fā)送同步組響應和修改狀態(tài)為穩(wěn)定了俘种,這個時候先執(zhí)行哪個動作都沒什么影響宙刘。
參考資料:
Kafka技術內(nèi)幕:圖文詳解Kafka源碼設計與實現(xiàn)