Interviewers often like to ask what zookeeper selection principle, what CAP theory, what data consistency. Often are asked tired, I would like to ask the interviewer, you will realize a simple cluster within the selection of the master? It is estimated that most of the interviewers themselves can not write out.
This article uses theJava cap (a poem)Netty Example of implementing a simple cluster master selection process.
This example shows multiple nodes electing a new master node by voting. netty is used for communication between the nodes, while each node is responsible for initiating and responding to election messages.
Cluster Master Selection Process
Mainstreaming process
Let's not talk about how zookeeper selects hosts, but let's just say that human beings select hosts using the principle of majority rule. When a human chooses a master, it goes through the following process:
(1) If I don't have a familiar or don't find one that is more capable than me, vote for myself first.
(2) As time goes on, maybe the people behind me introduce their respective characteristics and strengths, then I might change my vote to someone else.
(3) Everyone puts voting information into the tally box.
(4) The person with the most votes in the end is the leader.
Similarly, zookeeper follows the same process when selecting a master. Suppose there are 5 servers
- Server 1 votes for itself first
- Server 2, which gets up later, will also vote for itself, and then Server 1, observing that Server 2's id is larger, will vote for Server 2 instead
- Server 3, which gets up later, also votes for itself, and then both Service 1 and Server 2 change their votes to Server 3 when they realize that Server 3 has the bigger id. Server 3 is determined to be the leader.
- Server 4 gets up and also votes for itself, then realizes that server 3 already has 3 votes and immediately switches to server 3.
- Server 5 operates the same as Server 4.
Master selector agreement
The main selection process used in theover halfProtocol. The following types of messages will be required during the master selection process:
- Request for voting: The node sends its own vote request.
- Acceptance of votes: The remaining nodes make a judgment and accept the vote if they feel the id is larger.
- win an election: After being elected as a master node, broadcast the winning message.
code implementation
The following simulates the master selection process for 3 nodes with the following core steps:
1、Define message type, message object, node information
public enum MessageType {
VOTE_REQUEST, // Request for voting
VOTE, // referendum
ELECTED // News of the winner after the election is completed
}
public class ElectionMessage implements Serializable {
private MessageType type;
private int nodeId; // nodalID
private long zxId; // ZXID:alikeZooKeeperThe logic clock in the,For comparison
private int voteFor; // referendum给的nodalID
}
public class ElectionNode {
private int nodeId; // 当前nodalID
private long zxId; // 当前nodal的ZXID
private volatile int leaderId; // Current electionsLeader ID
private String host;
private int port;
private ConcurrentHashMap<Integer, Integer> voteMap = new ConcurrentHashMap<>(); // 此nodal对每个nodal的referendum情况
private int totalNodes; // 集群总nodal数
}
2, each node using Netty to start Server
public void start() throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap serverBootstrap = new ServerBootstrap();
(bossGroup, workerGroup)
.channel()
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
().addLast(
new ObjectDecoder((null)),
new ObjectEncoder(),
new ElectionHandler());
}
});
ChannelFuture future = (port).sync();
("Node " + nodeId + " started on port " + port);
// Start of the election process after start-up
startElection();
// ().closeFuture().sync();
} catch (Exception e) {
} finally {
// ();
// ();
}
}
3, after the start of the use of Netty to send voting requests
public void sendVoteRequest(String targetHost, int targetPort) {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
(group)
.channel()
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
().addLast(
new ObjectDecoder((null)),
new ObjectEncoder(),
new ElectionHandler());
}
});
ChannelFuture future = (targetHost, targetPort).sync();
ElectionMessage voteRequest = new ElectionMessage(.VOTE_REQUEST, nodeId, zxId, nodeId);
().writeAndFlush(voteRequest);
// ().closeFuture().sync();
} catch (Exception e) {
} finally {
// ();
}
}
4. After the node receives the voting request, do the relevant processing
The node does the relevant logical processing after receiving the message:Processing of vote requests, processing of vote confirmations, processing of master results。
**Handle the poll request:** Determine whether to accept the poll message or not. Only send a vote message if the master node is undecided and the zxId is large. If the poll request is accepted, update the local polling logic and send the polling node a poll acceptance message
Processing of confirmation votes: Update the local polling logic if the polling message is accepted.
Processing of selector results: Update the local master node if a message is received with the result of the master selection.
public class ElectionHandler extends ChannelInboundHandlerAdapter {
private final ElectionNode node; { private class ElectionHandler extends ChannelInboundHandlerAdapter {
public ElectionHandler(ElectionNode node) {
= node; }
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ElectionMessage electionMessage = (ElectionMessage) msg;
("Node " + () + " received: " + electionMessage);
if (() == .VOTE_REQUEST) {
// Determine if the vote message was received. Only send the vote message if the master node is not determined and the zxId is large
// If the poll request is accepted, update the local polling logic and send the polling node a poll acceptance message
if (() >= () && () == 0) {
(());
ElectionMessage voteMessage = new ElectionMessage(, (), (), (), ());
(voteMessage);
} else {
// If the master node has already been determined, send the ELECTED message directly
sendLeaderInfo(ctx);
}
} else if (() == ) {
// If the poll message was accepted, update the local polling logic.
if (() >= () && () == 0) {
(()).
} else {
// If the master node has already been identified, send the ELECTED message directly
sendLeaderInfo(ctx);
}
} else if (() == ) {
if (() == 0) {
(());
}
}
}
5. Accepting votes from other nodes
Here is a more critical step, when it is determined to accept a node, then update the number of local votes, and then determine whether the number of votes is more than half, more than half to determine the master node. At the same time, then broadcast the master node.
At this point, the remaining nodes receive the master selection confirmation message and update their own local master node information.
public void receiveVote(int nodeId) {
(nodeId, 1, Integer::sum);
// comparevoteslabor value,Take out the largest correspondingkey
int currentVotes = ().stream().max(Integer::compareTo).get();
if (currentVotes > totalNodes / 2 && leaderId == 0) {
setLeaderId(nodeId);
broadcastElected();
}
}
6. Broadcasting the results of the selection of the master
/**
* Broadcasting of election results
*/
private void broadcastElected() {
for (int i = 1; i <= totalNodes; i++) {
if (i != nodeId) {
sendElectedMessage(host, 9000 + i);
}
}
}
/**
* Send election results
*
* @param targetHost
* @param targetPort
*/
public void sendElectedMessage(String targetHost, int targetPort) {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
(group)
.channel()
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
().addLast(
new ObjectDecoder((null)),
new ObjectEncoder(),
new ElectionHandler());
}
});
ChannelFuture future = (targetHost, targetPort).sync();
ElectionMessage electedMessage = new ElectionMessage(, leaderId, zxId, leaderId);
().writeAndFlush(electedMessage);
// ().closeFuture().sync();
} catch (Exception e) {
} finally {
// ();
}
}
7. Complete code
Full Code:/yclxiao/specialty/blob/master/javacore/src/main/java/com/ycl/election/
summarize
This article mainly demonstrates a simple multi-Server election process of the master, the above code is a simple Netty-based implementation of the cluster election process example. In real scenarios, the election logic is far more complex than this, and needs to deal with more network anomalies, duplicate messages, concurrency issues, etc.
I hope it helps you, if you have any questions, you can add V to communicate.
The end of this article! Welcome to pay attention to, add V (ylxiao) exchange, the whole network can be searched (programmers half a cigarette)
Link to original article:/s/Lxt1ujFicJm-8KYBlVptZQ