zookeeper zab 简述



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);
        }
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值