Apache ZooKeeper - 集群中 Leader 的作用_事务的请求处理与调度分析
文章目錄
- 事務(wù)性請(qǐng)求處理
- Leader 事務(wù)處理分析
- 預(yù)處理階段
- 事務(wù)處理階段
- 事務(wù)執(zhí)行階段
- 響應(yīng)階段
- 源碼分析
- 小結(jié)
Leader 服務(wù)器在 ZooKeeper 中的作主要是處理事務(wù)性的會(huì)話請(qǐng)求以及管理 ZooKeeper 集群中的其他角色服務(wù)器
那么 在接收到來自客戶端的事務(wù)性會(huì)話請(qǐng)求后,ZooKeeper 集群內(nèi)部又是如何判斷會(huì)話的請(qǐng)求類型,以及轉(zhuǎn)發(fā)處理事務(wù)性請(qǐng)求的呢?
事務(wù)性請(qǐng)求處理
在 ZooKeeper 集群接收到來自客戶端的會(huì)話請(qǐng)求操作后,首先會(huì)判斷該條請(qǐng)求是否是事務(wù)性的會(huì)話請(qǐng)求。
對(duì)于事務(wù)性的會(huì)話請(qǐng)求,ZooKeeper 集群服務(wù)端會(huì)將該請(qǐng)求統(tǒng)一轉(zhuǎn)發(fā)給 Leader 服務(wù)器進(jìn)行操作。Leader 服務(wù)器內(nèi)部執(zhí)行該條事務(wù)性的會(huì)話請(qǐng)求后,再將數(shù)據(jù)同步給其他角色服務(wù)器,從而保證事務(wù)性會(huì)話請(qǐng)求的執(zhí)行順序,進(jìn)而保證整個(gè) ZooKeeper 集群的數(shù)據(jù)一致性。
在 ZooKeeper 集群的內(nèi)部實(shí)現(xiàn)中,是通過什么方法保證所有 ZooKeeper 集群接收到的事務(wù)性會(huì)話請(qǐng)求都能交給 Leader 服務(wù)器進(jìn)行處理的呢?
在 ZooKeeper 集群內(nèi)部,集群中除 Leader 服務(wù)器外的其他角色服務(wù)器接收到來自客戶端的事務(wù)性會(huì)話請(qǐng)求后,必須將該條會(huì)話請(qǐng)求轉(zhuǎn)發(fā)給 Leader 服務(wù)器進(jìn)行處理。 ZooKeeper 集群中的 Follow 和 Observer 服務(wù)器,都會(huì)檢查當(dāng)前接收到的會(huì)話請(qǐng)求是否是事務(wù)性的請(qǐng)求,如果是事務(wù)性的請(qǐng)求,那么就將該請(qǐng)求以 REQUEST 消息類型轉(zhuǎn)發(fā)給 Leader 服務(wù)器。
在 ZooKeeper集群中的服務(wù)器接收到該條消息后,會(huì)對(duì)該條消息進(jìn)行解析。分析出該條消息所包含的原始客戶端會(huì)話請(qǐng)求。之后將該條消息提交到自己的 Leader 服務(wù)器請(qǐng)求處理鏈中,開始進(jìn)行事務(wù)性的會(huì)話請(qǐng)求操作。如果不是事務(wù)性請(qǐng)求,ZooKeeper 集群則交由 Follow 和 Observer 角色服務(wù)器處理該條會(huì)話請(qǐng)求,如查詢數(shù)據(jù)節(jié)點(diǎn)信息。
Leader 事務(wù)處理分析
以客戶端發(fā)起的創(chuàng)建節(jié)點(diǎn)請(qǐng)求 setData 為例,具體看看 ZooKeeper 集群的底層處理過程。
在 ZooKeeper 集群接收到來自客戶端的一個(gè) setData 會(huì)話請(qǐng)求后,其內(nèi)部的處理邏輯基本可以分成四個(gè)部分 ,分別是預(yù)處理階段、事務(wù)處理階段、事務(wù)執(zhí)行階段、響應(yīng)客戶端。
預(yù)處理階段
在預(yù)處理階段,主要工作是通過網(wǎng)絡(luò) I/O 接收來自客戶端的會(huì)話請(qǐng)求。判斷該條會(huì)話請(qǐng)求的類型是否是事務(wù)性的會(huì)話請(qǐng)求,之后將該請(qǐng)求提交給PrepRequestProcessor 處理器進(jìn)行處理。封裝請(qǐng)求事務(wù)頭并檢查會(huì)話是否過期,最后反序列化事務(wù)請(qǐng)求信息創(chuàng)建 setDataRequest 請(qǐng)求,在 setDataRequest 記錄中包含了要?jiǎng)?chuàng)建數(shù)據(jù)的節(jié)點(diǎn)的路徑、數(shù)據(jù)節(jié)點(diǎn)的內(nèi)容信息以及數(shù)據(jù)節(jié)點(diǎn)的版本信息。最后將該請(qǐng)求存放在 outstandingChanges 隊(duì)列中等待之后的處理。
事務(wù)處理階段
在事務(wù)處理階段,ZooKeeper 集群內(nèi)部會(huì)將該條會(huì)話請(qǐng)求提交ProposalRequestProcessor 處理器進(jìn)行處理。
事務(wù)執(zhí)行階段
在經(jīng)過預(yù)處理階段和事務(wù)會(huì)話的投票發(fā)起等操作后,一個(gè)事務(wù)性的會(huì)話請(qǐng)求都已經(jīng)準(zhǔn)備好了,接下來就是在 ZooKeeper 的數(shù)據(jù)庫中執(zhí)行該條會(huì)話的數(shù)據(jù)變更操作。
在處理數(shù)據(jù)變更的過程中,ZooKeeper 內(nèi)部會(huì)將該請(qǐng)求會(huì)話的事務(wù)頭和事務(wù)體信息直接交給內(nèi)存數(shù)據(jù)庫 ZKDatabase 進(jìn)行事務(wù)性的持久化操作。之后返回 ProcessTxnResult 對(duì)象表明操作結(jié)果是否成功。
響應(yīng)階段
在 ZooKeeper 集群處理完客戶端 setData 方法發(fā)送的數(shù)據(jù)節(jié)點(diǎn)創(chuàng)建請(qǐng)求后,會(huì)將處理結(jié)果發(fā)送給客戶端。
在響應(yīng)客戶端的過程中,ZooKeeper 內(nèi)部首先會(huì)創(chuàng)建一個(gè) setDataResponse 響應(yīng)體類型,該對(duì)象主要包括當(dāng)前會(huì)話請(qǐng)求所創(chuàng)建的數(shù)據(jù)節(jié)點(diǎn),以及其最新狀態(tài)字段信息 stat。
之后創(chuàng)建請(qǐng)求響應(yīng)頭信息,響應(yīng)頭作為客戶端請(qǐng)求響應(yīng)的重要信息,客戶端在接收到 ZooKeeper 集群的響應(yīng)后,通過解析響應(yīng)頭信息中的事務(wù) ZXID 和請(qǐng)求結(jié)果標(biāo)識(shí)符 err 來判斷該條會(huì)話請(qǐng)求是否成功執(zhí)行。
源碼分析
首先,ZooKeeper 集群在收到客戶端發(fā)送的事務(wù)性會(huì)話請(qǐng)求后,會(huì)對(duì)該請(qǐng)求進(jìn)行預(yù)處理。在代碼層面,ZooKeeper 通過調(diào)用 PrepRequestProcessor 類來實(shí)現(xiàn)預(yù)處理階段的全部邏輯。
可以這樣理解:在處理客戶端會(huì)話請(qǐng)求的時(shí)候,首先調(diào)用的就是 PrepRequestProcessor 類。而在 PrepRequestProcessor 內(nèi)部,是通過 pRequest 方法判斷客戶端發(fā)送的會(huì)話請(qǐng)求類型。如果是諸如 setData 數(shù)據(jù)節(jié)點(diǎn)創(chuàng)建等事務(wù)性的會(huì)話請(qǐng)求,就調(diào)用 pRequest2Txn 方法進(jìn)一步處理。
protected void pRequest(Request request){...switch (request.type) {case OpCode.setData:SetDataRequest setDataRequest = new SetDataRequest(); pRequest2Txn(request.type, zks.getNextZxid(), request, setDataRequest, true);break;}}而在 pRequest2Txn 方法的內(nèi)部,就實(shí)現(xiàn)了預(yù)處理階段的主要邏輯。如下面的代碼所示,首先通過 checkSession 方法檢查該條會(huì)話請(qǐng)求是否有效(比如會(huì)話是否過期等),之后調(diào)用 checkACL 檢查發(fā)起會(huì)話操作的客戶端在 ZooKeeper 服務(wù)端是否具有相關(guān)操作的權(quán)限。最后將該條會(huì)話創(chuàng)建的相關(guān)信息,諸如 path 節(jié)點(diǎn)路徑、data 節(jié)點(diǎn)數(shù)據(jù)信息、version 節(jié)點(diǎn)版本信息等字段封裝成setDataRequest 類型并傳入到 setTxn 方法中,最后加入處理鏈中進(jìn)行處理。
case OpCode.setData:zks.sessionTracker.checkSession(request.sessionId, request.getOwner());SetDataRequest setDataRequest = (SetDataRequest)record;if(deserialize)ByteBufferInputStream.byteBuffer2Record(request.request, setDataRequest);path = setDataRequest.getPath();validatePath(path, request.sessionId);nodeRecord = getRecordForPath(path);checkACL(zks, request.cnxn, nodeRecord.acl, ZooDefs.Perms.WRITE, request.authInfo, path, null);int newVersion = checkAndIncVersion(nodeRecord.stat.getVersion(), setDataRequest.getVersion(), path);request.setTxn(new SetDataTxn(path, setDataRequest.getData(), newVersion));nodeRecord = nodeRecord.duplicate(request.getHdr().getZxid());nodeRecord.stat.setVersion(newVersion);addChangeRecord(nodeRecord);小結(jié)
主要梳理了 ZooKeeper 集群中 Leader 服務(wù)器是如何處理事務(wù)性的會(huì)話請(qǐng)求的,并且在處理完事務(wù)性的會(huì)話請(qǐng)求后,是如何通知其他角色服務(wù)器進(jìn)行同步操作的。
可以說在 ZooKeeper 集群處理事務(wù)性的請(qǐng)過程中,Follow 和 Observer 服務(wù)器主要負(fù)責(zé)接收客戶端的會(huì)話請(qǐng)求,并轉(zhuǎn)發(fā)給 Leader 服務(wù)器。而真正處理該條會(huì)話請(qǐng)求的是 Leader 服務(wù)器。
這就會(huì)引發(fā)一個(gè)問題:當(dāng)一個(gè)業(yè)務(wù)場景在查詢操作多而創(chuàng)建刪除等事務(wù)性操作少的情況下,ZooKeeper 集群的性能表現(xiàn)的就會(huì)很好。
而如果是在極端情況下,ZooKeeper 集群只有事務(wù)性的會(huì)話請(qǐng)求而沒有查詢操作,那么 Follow 和 Observer 服務(wù)器就只能充當(dāng)一個(gè)請(qǐng)求轉(zhuǎn)發(fā)服務(wù)器的角色, 所有的會(huì)話的處理壓力都在 Leader 服務(wù)器。
在處理性能上整個(gè)集群服務(wù)器的瓶頸取決于 Leader 服務(wù)器的性能。ZooKeeper 集群的作用只能保證在 Leader 節(jié)點(diǎn)崩潰的時(shí)候,重新選舉出 Leader 服務(wù)器保證系統(tǒng)的穩(wěn)定性。這也是 ZooKeeper 設(shè)計(jì)的一個(gè)缺點(diǎn)。
總結(jié)
以上是生活随笔為你收集整理的Apache ZooKeeper - 集群中 Leader 的作用_事务的请求处理与调度分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Apache ZooKeeper - L
- 下一篇: Apache ZooKeeper - 集