一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 理解zookeeper選舉機制

理解zookeeper選舉機制

2020-08-15 17:40min.jiang Java教程

本文主要介紹了zookeeper選舉機制的相關知識,具有很好的參考價值,下面跟著小編一起來看下吧

zookeeper集群

配置多個實例共同構成一個集群對外提供服務以達到水平擴展的目的,每個服務器上的數據是相同的,每一個服務器均可以對外提供讀和寫的服務,這點和redis是相同的,即對客戶端來講每個服務器都是平等的。

理解zookeeper選舉機制

這篇主要分析leader的選擇機制,zookeeper提供了三種方式:

  • leaderelection
  • authfastleaderelection
  • fastleaderelection

默認的算法是fastleaderelection,所以這篇主要分析它的選舉機制。

選擇機制中的概念

服務器id

比如有三臺服務器,編號分別是1,2,3。

編號越大在選擇算法中的權重越大。

數據id

服務器中存放的最大數據id.

值越大說明數據越新,在選舉算法中數據越新權重越大。

邏輯時鐘

或者叫投票的次數,同一輪投票過程中的邏輯時鐘值是相同的。每投完一次票這個數據就會增加,然后與接收到的其它服務器返回的投票信息中的數值相比,根據不同的值做出不同的判斷。

選舉狀態

  • looking,競選狀態。
  • following,隨從狀態,同步leader狀態,參與投票。
  • observing,觀察狀態,同步leader狀態,不參與投票。
  • leading,領導者狀態。

選舉消息內容

在投票完成后,需要將投票信息發送給集群中的所有服務器,它包含如下內容。

  • 服務器id
  • 數據id
  • 邏輯時鐘
  • 選舉狀態

選舉流程圖

因為每個服務器都是獨立的,在啟動時均從初始狀態開始參與選舉,下面是簡易流程圖。

理解zookeeper選舉機制

選舉狀態圖

描述leader選擇過程中的狀態變化,這是假設全部實例中均沒有數據,假設服務器啟動順序分別為:a,b,c。

理解zookeeper選舉機制

源碼分析

quorumpeer

主要看這個類,只有looking狀態才會去執行選舉算法。每個服務器在啟動時都會選擇自己做為領導,然后將投票信息發送出去,循環一直到選舉出領導為止。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public void run() {
  //.......
  try {
   while (running) {
    switch (getpeerstate()) {
    case looking:
     if (boolean.getboolean("readonlymode.enabled")) {
      //...
      try {
       //投票給自己...
       setcurrentvote(makelestrategy().lookforleader());
      } catch (exception e) {
       //...
      } finally {
       //...
      }
     } else {
      try {
       //...
       setcurrentvote(makelestrategy().lookforleader());
      } catch (exception e) {
       //...
      }     
     }
     break;
    case observing:
     //...
     break;
    case following:
     //...
     break;
    case leading:
     //...
     break;
    }
   }
  } finally {
   //...
  }
 }

fastleaderelection

它是zookeeper默認提供的選舉算法,核心方法如下:具體的可以與本文上面的流程圖對照。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
public vote lookforleader() throws interruptedexception {
  //...
  try {
   hashmap<long, vote> recvset = new hashmap<long, vote>();
 
   hashmap<long, vote> outofelection = new hashmap<long, vote>();
   int nottimeout = finalizewait;
   synchronized(this){
    //給自己投票
    logicalclock.incrementandget();
    updateproposal(getinitid(), getinitlastloggedzxid(), getpeerepoch());
   }
   //將投票信息發送給集群中的每個服務器
   sendnotifications();
   //循環,如果是競選狀態一直到選舉出結果
   while ((self.getpeerstate() == serverstate.looking) &&
     (!stop)){
    notification n = recvqueue.poll(nottimeout,
      timeunit.milliseconds);
    //沒有收到投票信息
    if(n == null){
     if(manager.havedelivered()){
      sendnotifications();
     } else {
      manager.connectall();
     }
     //...
    }
    //收到投票信息
    else if (self.getcurrentandnextconfigvoters().contains(n.sid)) {
     switch (n.state) {
     case looking:
      // 判斷投票是否過時,如果過時就清除之前已經接收到的信息     
      if (n.electionepoch > logicalclock.get()) {
       logicalclock.set(n.electionepoch);
       recvset.clear();
       //更新投票信息
       if(totalorderpredicate(n.leader, n.zxid, n.peerepoch,
         getinitid(), getinitlastloggedzxid(), getpeerepoch())) {
        updateproposal(n.leader, n.zxid, n.peerepoch);
       } else {
        updateproposal(getinitid(),
          getinitlastloggedzxid(),
          getpeerepoch());
       }
       //發送投票信息
       sendnotifications();
      } else if (n.electionepoch < logicalclock.get()) {
       //忽略
       break;
      } else if (totalorderpredicate(n.leader, n.zxid, n.peerepoch,
        proposedleader, proposedzxid, proposedepoch)) {
       //更新投票信息
       updateproposal(n.leader, n.zxid, n.peerepoch);
       sendnotifications();
      }    
      recvset.put(n.sid, new vote(n.leader, n.zxid, n.electionepoch, n.peerepoch));
      //判斷是否投票結束
      if (termpredicate(recvset,
        new vote(proposedleader, proposedzxid,
logicalclock.get(), proposedepoch))) {
       // verify if there is any change in the proposed leader
       while((n = recvqueue.poll(finalizewait,
         timeunit.milliseconds)) != null){
        if(totalorderpredicate(n.leader, n.zxid, n.peerepoch,
          proposedleader, proposedzxid, proposedepoch)){
         recvqueue.put(n);
         break;
        }
       }
       if (n == null) {
        self.setpeerstate((proposedleader == self.getid()) ?
 serverstate.leading: learningstate());
        vote endvote = new vote(proposedleader,
proposedzxid, proposedepoch);
        leaveinstance(endvote);
        return endvote;
       }
      }
      break;
     case observing:
      //忽略
      break;
     case following:
     case leading:
      //如果是同一輪投票
      if(n.electionepoch == logicalclock.get()){
       recvset.put(n.sid, new vote(n.leader, n.zxid, n.electionepoch, n.peerepoch));
       //判斷是否投票結束
       if(termpredicate(recvset, new vote(n.leader,
           n.zxid, n.electionepoch, n.peerepoch, n.state))
           && checkleader(outofelection, n.leader, n.electionepoch)) {
        self.setpeerstate((n.leader == self.getid()) ?
serverstate.leading: learningstate());
        vote endvote = new vote(n.leader, n.zxid, n.peerepoch);
        leaveinstance(endvote);
        return endvote;
       }
      }
      //記錄投票已經完成
      outofelection.put(n.sid, new vote(n.leader,
        ignorevalue, ignorevalue, n.peerepoch, n.state));
      if (termpredicate(outofelection, new vote(n.leader,
        ignorevalue, ignorevalue, n.peerepoch, n.state))
        && checkleader(outofelection, n.leader, ignorevalue)) {
       synchronized(this){
        logicalclock.set(n.electionepoch);
        self.setpeerstate((n.leader == self.getid()) ?
serverstate.leading: learningstate());
       }
       vote endvote = new vote(n.leader, n.zxid, n.peerepoch);
       leaveinstance(endvote);
       return endvote;
      }
      break;
     default:
      //忽略
      break;
     }
    } else {
     log.warn("ignoring notification from non-cluster member " + n.sid);
    }
   }
   return null;
  } finally {
   //...
  }
 }

判斷是否已經勝出

默認是采用投票數大于半數則勝出的邏輯。

選舉流程簡述

目前有5臺服務器,每臺服務器均沒有數據,它們的編號分別是1,2,3,4,5,按編號依次啟動,它們的選擇舉過程如下:

  • 服務器1啟動,給自己投票,然后發投票信息,由于其它機器還沒有啟動所以它收不到反饋信息,服務器1的狀態一直屬于looking。
  • 服務器2啟動,給自己投票,同時與之前啟動的服務器1交換結果,由于服務器2的編號大所以服務器2勝出,但此時投票數沒有大于半數,所以兩個服務器的狀態依然是looking。
  • 服務器3啟動,給自己投票,同時與之前啟動的服務器1,2交換信息,由于服務器3的編號最大所以服務器3勝出,此時投票數正好大于半數,所以服務器3成為領導者,服務器1,2成為小弟。
  • 服務器4啟動,給自己投票,同時與之前啟動的服務器1,2,3交換信息,盡管服務器4的編號大,但之前服務器3已經勝出,所以服務器4只能成為小弟。
  • 服務器5啟動,后面的邏輯同服務器4成為小弟。

以上就是本文的全部內容,希望本文的內容對大家的學習或者工作能帶來一定的幫助,同時也希望多多支持服務器之家!

原文鏈接:http://www.cnblogs.com/ASPNET2008/p/6421571.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 毛片免费的 | 情乱奶水欲 | 色综合久久98天天综合 | 鄂州一家三口完整版免费 | 女人c交zzzooo在线观看 | 我和岳的性事小说 | 久久久这里有精品999 | 成人免费淫片95视频观看网站 | 精品久久伦理中文字幕 | 欧美帅老头oldmangay | 婷婷影院在线观看 | 欧美久久综合网 | 日韩在线免费 | 四虎影库紧急大通知 | 亚洲精品资源在线 | 欧美成人一区二区三区 | 91九色视频无限观看免费 | 99热这里只有精品国产在热久久 | 妇伦小说 | 国产免费一区二区 | 久久精品麻豆国产天美传媒果冻 | 性做久久久久久 | 性姿势女人嗷嗷叫图片 | 国产精品永久免费视频观看 | 欧美日韩中文国产一区二区三区 | 四虎影视4hutv最新地址在线 | 亚洲精品91大神在线观看 | 99热在这里只有精品 | 俄罗斯三级完整版在线观看 | 欧美图片另类小说综合 | 深夜视频免费看 | 青草娱乐极品免费视频 | 丰满大乳欲妇三级k8 | 性的张力| 四虎4hu永久免费 | 国产成人v爽在线免播放观看 | 胸大的姑娘中文字幕视频 | 精品免费视在线观看 | 免费看日本 | 国产精品久久久久久久久 | 高跟丝袜hdvideossex |