ZooKeeper順序節(jié)點(diǎn)之Sequence原理

sequence自增原理是什么?

為什么get命令看到的cversion和實(shí)際存儲(chǔ)的cversion不一樣?

sequence自增怎么保證無(wú)并發(fā)問(wèn)題?單節(jié)點(diǎn)和多節(jié)點(diǎn)?

  1. sequence自增原理是什么?

    // 代碼取自(服務(wù)端代碼)org.apache.zookeeper.server.PrepRequestProcessor#pRequest2TxnCreate
    ChangeRecord parentRecord = getRecordForPath(parentPath);
    checkACL(zks, parentRecord.acl, ZooDefs.Perms.CREATE, request.authInfo);
    int parentCVersion = parentRecord.stat.getCversion();
    if (createMode.isSequential()) {
        // 如果是順序節(jié)點(diǎn)的話,從父節(jié)點(diǎn)中取出cversion的值作為sequence.
        path = path + String.format(Locale.ENGLISH, "%010d", parentCVersion);
    }
    
  2. 為什么get命令看到的cversion和實(shí)際存儲(chǔ)的cversion不一樣?

    知道了sequence取值邏輯后,用get命令查看父節(jié)點(diǎn)的cversion字段,卻發(fā)現(xiàn)總是和新生成節(jié)點(diǎn)的sequence不一致?最后定位到get命令的代碼.

    // 代碼取自(服務(wù)端代碼)org.apache.zookeeper.server.DataNode#copyStat
    synchronized public void copyStat(Stat to) {
            to.setAversion(stat.getAversion());
            to.setCtime(stat.getCtime());
            to.setCzxid(stat.getCzxid());
            to.setMtime(stat.getMtime());
            to.setMzxid(stat.getMzxid());
            to.setPzxid(stat.getPzxid());
            to.setVersion(stat.getVersion());
            to.setEphemeralOwner(getClientEphemeralOwner(stat));
            to.setDataLength(data == null ? 0 : data.length);
            int numChildren = 0;
            if (this.children != null) {
                numChildren = children.size();
            }
         // 重點(diǎn)!
            // when we do the Cversion we need to translate from the count of the creates
            // to the count of the changes (v3 semantics)
            // for every create there is a delete except for the children still present
         // 當(dāng)我們進(jìn)行Cversion時(shí),我們需要從create的數(shù)量中進(jìn)行翻譯更改計(jì)數(shù)(v3語(yǔ)義)對(duì)于每個(gè)創(chuàng)建都有一個(gè)刪除,除了仍然存在的孩子(Google 翻譯)
            to.setCversion(stat.getCversion()*2 - numChildren);
            to.setNumChildren(numChildren);
    }
    
  3. sequence自增怎么保證無(wú)并發(fā)問(wèn)題?單節(jié)點(diǎn)和多節(jié)點(diǎn)?

    先來(lái)說(shuō)多節(jié)點(diǎn)吧,(參考網(wǎng)上通常的說(shuō)法)當(dāng)一個(gè)客戶端進(jìn)行寫(xiě)數(shù)據(jù)請(qǐng)求時(shí),會(huì)指定ZooKeeper集群中的一個(gè)Server節(jié)點(diǎn),如果該節(jié)點(diǎn)為Follower,則該節(jié)點(diǎn)會(huì)把寫(xiě)請(qǐng)求轉(zhuǎn)發(fā)給Leader,Leader通過(guò)內(nèi)部的協(xié)議進(jìn)行原子廣播,直到一半以上的server節(jié)點(diǎn)都成功寫(xiě)入數(shù)據(jù),這次寫(xiě)請(qǐng)求便算是成功,然后Leader便會(huì)通過(guò)通知相應(yīng)的Follower節(jié)點(diǎn)寫(xiě)請(qǐng)求成功,該節(jié)點(diǎn)向client返回寫(xiě)入成功.
    本質(zhì)上說(shuō)還是把多節(jié)點(diǎn)寫(xiě)操作轉(zhuǎn)換成了單節(jié)點(diǎn)的寫(xiě)操作,這樣就可以在單節(jié)點(diǎn)進(jìn)行并發(fā)控制了,效率更高.而在單節(jié)點(diǎn)做并發(fā)控制的話就方便的多了,通過(guò)PrepRequestProcessor->SyncRequestProcessor->FinalRequestProcessor->ZooKeeperServer->ZKDatabase->DataTree鏈路處理.有興趣可以自己翻翻代碼哦.

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容