Zookeeper学习视频心得(二)zookeeper监听器、API、ZAB协议

同步通信和异步通信:回调函数存于异步通信,异步通信至少两个线程起步

1、Zookeeper监听器原理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fj19uDDR-1610109818570)(C:\Users\xiaoyoupei\AppData\Roaming\Typora\typora-user-images\image-20210107204147889.png)]

1)、监听原理

①、首先要有一个main()线程

②、在main线程中创建Zookeeper客户端,这时就会创建两个线程,一个负责网络连接通信(connet) ,一个负责监听( listener) 。

③、通过connect线程将注册的监听事件发送给Zookeeper。

④、在Zookeeper的注册监听器列表中将注册的监听事件添加到列表中。

⑤、Zookeeper监听到有数据或路径变化,就会将这个消息发送给listener线程。

⑥ 、listener线程内部调用了process()方法。

2)、常见的监听

①、监听节点数据的变化

get path[watch]

②、监听子节点增减的变化

ls path [watch]

2、ZooKeeperAPI

/**
 * @author xiaoyoupei
 * @date 2021-01-07 19:15
 * @Description:
 */
public class ZkClient {

    private ZooKeeper zooKeeper;

    @Before
    public void before() throws IOException {
        //zookeeper连接地址
        String connectString = "test:2181,test1:2181,test2:2181";

        //超时时间
        int sessionTimeout = 2000;

        //1、创建一个Zookeeper对象
        zooKeeper = new ZooKeeper(connectString, sessionTimeout
                , new Watcher() {
            @Override
            //zookeeper监听的回调函数
            public void process(WatchedEvent watchedEvent) {

            }
        });
    }

    /**
     * 创建新节点
     */
    @Test
    public void create() throws IOException, KeeperException, InterruptedException {

        //2、搞事情
        zooKeeper.create(
                "/testAPI",//路径名
                "123".getBytes(),//节点的值(字节数组)
                ZooDefs.Ids.OPEN_ACL_UNSAFE,//访问控制列表
                CreateMode.PERSISTENT//永久有效(节点数据类型)异步通信
        );

    }

    /**
     * 查看目录下所有子节点,并且自定义监听(如果有什么操作会调用回调函数,比如删除节点)
     */
    @Test
    public void ls() throws KeeperException, InterruptedException {
        List<String> children = zooKeeper.getChildren("/",//查看的路径
                new Watcher() {
                    @Override
                    public void process(WatchedEvent watchedEvent) {
                        System.out.println("自定义回调函数");
                    }
                }
        );

        for (String child : children) {
            System.out.println(child);
        }

        //阻塞主进程,因为后台的守护线程盯着主线程,主线程一结束,守护线程也结束
        Thread.sleep(Long.MAX_VALUE);
    }

    /**
     * 查询节点的值
     */
    @Test
    public void get() throws KeeperException, InterruptedException, IOException {
        //节点状态(stat结构体)
        Stat stat = new Stat();
        byte[] data = zooKeeper.getData("/testAPI", false, stat);

        System.out.println(stat.toString());//节点的状态信息
        System.out.write(data);
        System.out.println();
    }

    /**
     * 查询一个节点的状态
     */
    @Test
    public void stat() throws KeeperException, InterruptedException {
        //查看节点是否存在
        Stat stat = zooKeeper.exists("/testAPI", false);
        if (stat == null) {
            System.out.println("节点不存在");
        } else {
            System.out.println(stat);
        }
    }

    /**
     * 设置节点的具体值
     */
    @Test
    public void set() throws KeeperException, InterruptedException {
        String node = "/testAPI";
        Stat stat = zooKeeper.exists(node, false);

        if (stat == null) {
            System.out.println("节点不存在");
        } else {
            zooKeeper.setData(
                    "/testAPI",//节点位置
                    "xyp".getBytes(),//要改成的具体值

                    /**
                     * 数据变化号
                     * (在我们进行此操作时很有可能有人正在修改,数据产生变化,
                     * 因此设置一个数据的变化号(数据的第几个版本))
                     */
                    stat.getVersion()
            );
        }
    }

    /**
     * 删除节点
     */
    @Test
    public void delete() throws KeeperException, InterruptedException {
        zooKeeper.delete(
                "/testAPI",
                1);
    }

    @After
    public void after() throws InterruptedException {
        //3、关闭资源
        zooKeeper.close();
    }
}

3、Zookeeper的ZAB协议(半数协议)

​ zookeeper自己开发的一套协议。首先集群里面都是地位平等的,如果没有Leader,就在集群中选出Leader,如果有Leader就正常操作。

1)、选举机制(没有Leader选Leader)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KDf75GAe-1610109818573)(C:\Users\xiaoyoupei\AppData\Roaming\Typora\typora-user-images\image-20210108110700474.png)]

①、过程

a、服务器1启动,发起一次选举。服务器1投自己一票。此时服务器1票数一票,不够半数以上(3票),选举无法完成,服务器1状态保持为LOOKING;

b、服务器2启动,再发起一次选举。服务器1和2分别投自己一票并交换选票信息:此时服务器1发现服务器2的ID比自己目前投票推举的(服务器1)大,更改选票为推举服务器2。此时服务器1票数0票,服务器2票数2票,没有半数以上结果,选举无法完成,服务器1,2状态保持LOOKING

c、服务器3启动,发起一次选举。此时服务器1和2都会更改选票为服务器3。此次投票结果:服务器1为0票,服务器2为0票,服务器3为3票。此时服务器3的票数已经超过半数,服务器3当选Leader。服务器1,2更改状态为FOLLOWING,服务器3更改状态为LEADING;

d、服务器4启动,发起一次选举。此时服务器1,2,3已经不是LOOKING状态,不会更改选票信息。交换选票信息结果:服务器3为3票,服务器4为1票。此时服务器4服从多数,更改选票信息为服务器3,并更改状态为FOLLOWING;

e、服务器5启动,同4一样当小弟。

②、备注:

​ id先看每个服务器的zxid(每次进行操作的变动号),看谁的大,谁的大就是数据新,如果zxid相等就进一步比较myid(myid不可能相等的);找Leader和选举是同时进行的,只有Looking状态的机器才是“墙头草”,如果想优先让谁成为leader可以把myid调大。

③、通俗易懂:

​ 5台机器群起就是最后一个当Leader,单个启动就是第3个当Leader;5台机器,第3个为Leader,第3个挂了,选举第5个当Leader。

④、提问:如果后面的有更厉害的怎么办?

回答:不会,已经选好了Leader就不会改动,后面的就只会同步数据作为Following。

2)、写数据流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UnFGF3YQ-1610109818574)(C:\Users\xiaoyoupei\AppData\Roaming\Typora\typora-user-images\image-20210108201339266.png)]

①、补充:

当有个跟从者提出不同意的时候,他会“原地自杀”,然后重启,再向Leader同步数据

②、提问:什么情况下节点不同意?

​ 当Leader发布写请求的时候server一定有一个zxid(Leader发布请求的时候编写好的)但是每个server都有自己的最新的zxid,只要Leader发来的zxid比自己的zxid大,他就同意,反之则不同意。

③、提问:如果Leader提出,半数不同意怎么办?

Leader自杀,重选Leader(概率很小)

4、zookeeper群起脚本

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NY9wcTRK-1610109818575)(C:\Users\xiaoyoupei\AppData\Roaming\Typora\typora-user-images\image-20210108191635698.png)]

1)、备注:

$#表示所有参数的个数;ssh $i表示免密登录;2表示标准错误(stderr);/dev/null是一个特殊的设备文件,这个文件接收到任何数据都会被丢弃。因此,null这个设备通常也被称为位桶(bit bucket)或黑洞;2>/dev/null的意思就是将标准错误stderr删掉。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

友培

数据皆开源!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值