ZooKeeper 소스 해석: Leader 선거
6728 단어 zookeeper
이 작업의 핵심 사상은 먼저 EPHEMERAL의 노드를 만드는 것이다. 예를 들어 "/election"이다.그리고 모든 ZooKeeper 서버는 이 디렉터리에 SEQUENCE | EPHEMERAL 형식의 노드를 만듭니다. 예를 들어 "/election/nu"입니다.SEQUENCE 로고에서 ZooKeeper는 자동으로 모든 ZooKeeper 서비스에 앞에서 지정한 번호보다 큰 번호를 할당합니다.노드 ZooKeeper 서버에 최소 번호가 있는 서버가 Leader가 됩니다.
실제 작업에서 Leader 서버가 고장났을 때 시스템은 다음 ZooKeeper 서버를 Leader로 신속하게 선택할 수 있음을 보증해야 한다.간단한 방안은 모든 Follower가 리더에 대응하는 노드를 감시하도록 하는 것이다.Leader에 장애가 발생하면 Leader에 대응하는 임시 노드가 자동으로 삭제됩니다. 이 동작은 Leader를 감시하는 모든 서버의watch를 터치합니다.이렇게 하면 이 서버들은 Leader 고장 소식을 받고 다음 Leader 선거 조작을 진행할 것이다.그러나 이런 조작은'종중효과'의 발생을 초래할 것이다. 특히 집단에 서버가 많고 광대역 지연이 비교적 클 때 더욱 뚜렷해진다.ZooKeeper에서 대중 효과의 발생을 피하기 위해 이것은 이렇게 이루어진다. 모든 Follower는 Follower 집단에서 자신의 노드 번호보다 작은 노드 중 x번호가 가장 큰 노드에watch를 설정한다.Followers가 설정한 watch가 촉발되었을 때만 Leader 선거 조작을 깨울 수 있습니다. 일반적인 상황에서 이것은 집단의 다음 Leader가 될 것입니다.분명히 이 Leader 선거의 조작 속도는 매우 빠르다.매번 Leader 선거는 거의 하나의 Follower 작업만 다루기 때문이다.다음은 원본 코드가 어떻게 실현되었는지 봅시다
org.apache.zookeeper.recipes.leader.LeaderElectionSupport
구체적인 실현 논리는 이 종류에 있다.우선 start 방법이 하나 있습니다. 이 방법에서 먼저 호출된 것을 볼 수 있습니다makeOffer(); determineElectionStatus();
/**
*
*/
public synchronized void start() {
state = State.START;
//
dispatchEvent(EventType.START);
LOG.info("Starting leader election support");
if (zooKeeper == null) {
throw new IllegalStateException(
"No instance of zookeeper provided. Hint: use setZooKeeper()");
}
if (hostName == null) {
throw new IllegalStateException(
"No hostname provided. Hint: use setHostName()");
}
try {
makeOffer();
determineElectionStatus();
} catch (KeeperException | InterruptedException e) {
becomeFailed(e);
}
}
makeOffer() 방법을 살펴보겠습니다. 이 방법은 주로 임시 노드를 만드는 것입니다.
/**
* root
* @throws KeeperException
* @throws InterruptedException
*/
private void makeOffer() throws KeeperException, InterruptedException {
state = State.OFFER;
dispatchEvent(EventType.OFFER_START);
LeaderOffer newLeaderOffer = new LeaderOffer();
byte[] hostnameBytes;
synchronized (this) {
newLeaderOffer.setHostName(hostName);
hostnameBytes = hostName.getBytes();
newLeaderOffer.setNodePath(zooKeeper.create(rootNodeName + "/" + "n_",
hostnameBytes, ZooDefs.Ids.OPEN_ACL_UNSAFE,
//
CreateMode.EPHEMERAL_SEQUENTIAL));
leaderOffer = newLeaderOffer;
}
LOG.debug("Created leader offer {}", leaderOffer);
dispatchEvent(EventType.OFFER_COMPLETE);
}
그리고 바로
determineElectionStatus()
이 방법은 파일 목록 아래의 모든 파일을 가져옵니다. 가장 작은 것은leader로 설정된 다른 노드에 이전의 감청을 추가합니다.
/**
*
* leader
* @throws KeeperException
* @throws InterruptedException
*/
private void determineElectionStatus() throws KeeperException, InterruptedException {
state = State.DETERMINE;
dispatchEvent(EventType.DETERMINE_START);
LeaderOffer currentLeaderOffer = getLeaderOffer();
String[] components = currentLeaderOffer.getNodePath().split("/");
currentLeaderOffer.setId(Integer.valueOf(components[components.length - 1].substring("n_".length())));
List leaderOffers = toLeaderOffers(zooKeeper.getChildren(rootNodeName, false));
/*
* For each leader offer, find out where we fit in. If we're first, we
* become the leader. If we're not elected the leader, attempt to stat the
* offer just less than us. If they exist, watch for their failure, but if
* they don't, become the leader.
*/
for (int i = 0; i < leaderOffers.size(); i++) {
LeaderOffer leaderOffer = leaderOffers.get(i);
if (leaderOffer.getId().equals(currentLeaderOffer.getId())) {
LOG.debug("There are {} leader offers. I am {} in line.", leaderOffers.size(), i);
dispatchEvent(EventType.DETERMINE_COMPLETE);
if (i == 0) {
// leader
becomeLeader();
} else {
// leader
becomeReady(leaderOffers.get(i - 1));
}
/* Once we've figured out where we are, we're done. */
break;
}
}
}
리더가 되지 않은 노드가 이전 노드를 감청하지 않으면 이전 노드가 고장나면 위의 방법을 다시 실행합니다
private void becomeReady(LeaderOffer neighborLeaderOffer)
throws KeeperException, InterruptedException {
LOG.info(
"{} not elected leader. Watching node: {}",
getLeaderOffer().getNodePath(),
neighborLeaderOffer.getNodePath());
/*
* Make sure to pass an explicit Watcher because we could be sharing this
* zooKeeper instance with someone else.
*/
/**
*
* watch, determineElectionStatus
*/
Stat stat = zooKeeper.exists(neighborLeaderOffer.getNodePath(), this);
if (stat != null) {
dispatchEvent(EventType.READY_START);
LOG.debug(
"We're behind {} in line and they're alive. Keeping an eye on them.",
neighborLeaderOffer.getNodePath());
state = State.READY;
dispatchEvent(EventType.READY_COMPLETE);
} else {
/*
* If the stat fails, the node has gone missing between the call to
* getChildren() and exists(). We need to try and become the leader.
*/
LOG.info(
"We were behind {} but it looks like they died. Back to determination.",
neighborLeaderOffer.getNodePath());
determineElectionStatus();
}
}
더 많은 주석은 여기 보시면 돼요.https://github.com/haha174/zookeeper/commit/1174717483578074654bbc6a8a1e4744b9c255a9
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
ZooKeeper 서버의 예는 하나뿐입니다.-- Start zookeeper-3.4.6/conf 디렉터리에 zoo_sample.cfg의 파일입니다. 이 파일을zoo로 개명합니다.cfg, 파일 이름은zoo만 가능합니다.cfg, ZooKeeper의 스크립트가 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.