import com.google.common.base.Objects;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
public class TestZAB {
static Set<X> x1 = Sets.newConcurrentHashSet();
static Set<X> x2 = Sets.newConcurrentHashSet();
static Set<X> x3 = Sets.newConcurrentHashSet();
static class X implements Runnable{
// zoo.cfg 配置3个
private static final int clusterNum = 3;
public static final List<X> cluster = Lists.newArrayList();
public X() {
// 加入集群
cluster.add(this);
}
private int myid;
// epoch + inc is zxid
private int epoch;
private int inc;
private int leader;
private String state = "LOOKING";
private Set<X> mailbox;
@Override
public void run() {
broadcastVote();
while (true) {
sleep();
if (mailbox.isEmpty()) {
broadcastVote();
continue;
}
System.out.println(myid + "查看信箱" + mailbox.toString());
X leader = this;
// zxid > myid
for (X l : mailbox) {
if (l.epoch > leader.epoch) {
leader = l;
} else if (l.myid > leader.myid) {
leader = l;
}
}
// 票数被击败
if (leader != this && state.equals("LOOKING")) {
// 修改信封内容,选举该leader
this.leader = leader.leader;
for (X x : cluster) {
// 除了自己都发出去
if (x != this) {
System.out.println(myid + "投票被击败 认为最有可能的leader" + leader.myid + ",发送该投票给" + x.myid);
x.vote(this);
}
}
}
// 归拢票数
int leaderNum = 0;
for (X l : mailbox) {
if (leader.leader == l.leader) {
leaderNum ++;
}
}
if (leaderNum > clusterNum / 2) {
if (leader == this) {
this.state = "LEADING";
this.epoch ++;
this.inc = 0; // inc清0
System.out.println(myid + "投票结果 成为leader");
} else {
this.state = "FOLLOWING";
// leader是谁
this.leader = leader.leader;
System.out.println(myid + "投票结果 成为Follower");
}
break;
}
}
}
private void vote(X x) {
this.mailbox.add(x);
}
private boolean followerWrite(String data, X leader) {
if (leader.myid != this.leader) {
System.out.println("接收到非leader发来的写请求,拒绝该请求");
return false;
} else {
System.out.println(myid + " follow data write: " + data);
return true;
}
}
private boolean write(String data) {
if (this.state.equals("LOOKING")) {
System.out.println("选举阶段,无法处理请求!");
return false;
}
if (this.state.equals("LEADING")) {
int i = 0;
for (X x : cluster) {
if (x != this) {
if (x.followerWrite(data, this)) {
i ++ ;
}
}
}
if (i > clusterNum / 2) {
System.out.println(myid + " 请求" + data + " leader写入成功");
this.inc = this.inc + 1;
return true;
} else {
// 可能发生网络分区, leader被隔离, 其他节点可能已经选出来新的leader,
// 这个时候有可能两个leader, 由于写入需要半数以上,所以当前leader写入失败
System.out.println(myid + " 过半未写入, 写入失败");
return false;
}
} else {
for (X x : cluster) {
if (x.state.equals("LEADING")) {
System.out.println(myid + " 转发给leader " + x.leader + " 数据内容" + data);
return x.write(data);
}
}
System.out.println("没有leader, 处理请求失败!!");
return false;
}
}
private void broadcastVote() {
for (X node : cluster) {
// 投自己一票
node.vote(this);
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof X)) return false;
X x = (X) o;
return myid == x.myid;
}
@Override
public int hashCode() {
return Objects.hashCode(myid);
}
@Override
public String toString() {
return "X{" +
"self=" + myid +
", epoch=" + epoch +
", leader=" + leader +
", state='" + state + '\'' +
'}';
}
}
public static void main(String[] args) {
X xt1 = new X();
X xt2 = new X();
X xt3 = new X();
xt1.myid = 1;
xt1.epoch = 0;
xt1.leader = 1;
xt1.mailbox = x1;
xt2.myid = 2;
xt2.epoch = 0;
xt2.leader = 2;
xt2.mailbox = x2;
xt3.myid = 3;
xt3.epoch = 0;
xt3.leader = 3;
xt3.mailbox = x3;
new Thread(xt1).start();
new Thread(xt2).start();
new Thread(xt3).start();
sleep();
sleep();
sleep();
sleep();
for (X x : X.cluster) {
x.write("xxxx");
}
}
private static void sleep() {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
zookeeper zab 简述
于 2023-03-14 18:57:05 首次发布