Zookeeper从零入门笔记

一、入门

1. 概述

在这里插入图片描述
在这里插入图片描述

2. 特点

在这里插入图片描述

3. 数据结构

在这里插入图片描述

4. 应用场景

统一命名服务:nginx也可以实现
统一配置管理:
统一集群管理:
服务器动态上下线:
软负载均衡:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、本地

1.安装

2. 参数解读

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三、集群操作

3.1.1 集群安装

在这里插入图片描述
在这里插入图片描述

遇到问题:1防火墙未关闭,2配置错误
sudo systemctl stop firewalld
加到zok.conf中:

############cluster#################
server.2=192.168.88.130:2888:3888
server.3=192.168.88.131:2888:3888
server.4=192.168.88.132:2888:3888

3.2 选举机制

1. 第一次启动

在这里插入图片描述

2. 非第一次启动

在这里插入图片描述

3.3 ZK集群启动停止脚本

#!/bin/bash
case $1 in
"start"){
	for i in 192.168.88.130 192.168.88.131 192.168.88.132
	do
		echo -------- zookeeper $i 启动 ------------
		ssh $i "/opt/module/zookeeper-3.5.7/bin/zkServer.sh start"
	done
}
;;
"stop"){
	for i in 192.168.88.130 192.168.88.131 192.168.88.132
	do
		echo -------- zookeeper $i 停止 ------------
		ssh $i "/opt/module/zookeeper-3.5.7/bin/zkServer.sh stop"
	done
}
;;
"status"){
	for i in 192.168.88.130 192.168.88.131 192.168.88.132
	do
		echo -------- zookeeper $i 状态 ------------
		ssh $i "/opt/module/zookeeper-3.5.7/bin/zkServer.sh status"
	done
}
;;
esac

3.4 客户端命令行操作

3.2.1 命令行语法

在这里插入图片描述

在这里插入图片描述

3.2.2 节点类型(持久/短暂/有序号/无序号)

在这里插入图片描述
临时节点:退出客户端以后删除
有序节点:可重复,key后自带序号

create /sanguo/shuguo/zhangfei #创建永久无序节点
create -s /sanguo/shuguo/guanyu #创建永久有序节点
create -s -e /sanguo/wuguo/zhouyu1 #创建临时有序节点
create -e /sanguo/wuguo/zhouyu2 #创建临时无序节点

3.2.4 监听器原理

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.3 删除节点

在这里插入图片描述

3.5 客户端API操作

在这里插入图片描述
在这里插入图片描述

3.6 监听节点变化

在这里插入图片描述

3.7 判断Znode是否存在

3.8 写数据原理

分为两种情况:
1、请求发送给Leader节点;

  1. Client发送write请求给Leader,Leader收到消息先写
  2. Leader将write请求转发给下一个Follower节点,Follow收到写入 完成后回一个ack给上一个节点(Leader)
  3. 大于半数的Leader节点完成写入(共3,完成2),Leader返回给Clinet一个ack表示完成
  4. Leader继续给其他Follower发送write请求,Follower接收到请求写入,完成后返回ack
    在这里插入图片描述

2、请求发送给Follower节点;

  1. Client发送write请求给Follower,Follower收到消息先转发给Leader
  2. Leader接收到write请求,先执行,然后转发给Follower
  3. Follower接收到write请求。执行,然后回复一个ack
  4. 大于半数节点已write,Leader返回一个ack给最先接触到Client的节点(Follower),Follower再返回一个ack给Client
  5. Leader给剩下的Follower发送write请求,Follower写完回复ack给Leader
    在这里插入图片描述

四、服务器动态上下线监听案例

在这里插入图片描述

package com.atguigu.case1;

import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;

import java.io.IOException;
import java.sql.Array;
import java.util.ArrayList;
import java.util.List;

/**
 * 2023年11月24日
 * <p>
 * case1 服务器动态上下限
 * <p>
 * 1、获取zk连接
 * 2、监听节点
 * 3、业务代码(睡觉
 */
public class DistributeClient {
    ZooKeeper zooKeeper;

    public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
        DistributeClient zk = new DistributeClient();
        zk.connect();

        zk.watcherList();

        zk.business();
    }

    private void business() throws InterruptedException {
        Thread.sleep(Long.MAX_VALUE);
    }

    private void watcherList() throws InterruptedException, KeeperException {
        List<String> children = zooKeeper.getChildren("/servers", true, null);
        ArrayList<String> strings = new ArrayList<String>();

        for (String child : children) {
            byte[] data = zooKeeper.getData("/servers/" + child, false, null);
            strings.add(new String(data));
        }
        System.out.println(strings);
    }

    private void connect() throws IOException {
        String connectString = "192.168.88.130:2181,192.168.88.131:2181,192.168.88.132:2181";
        int sessionTimeout = 300000;
        zooKeeper = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
            public void process(WatchedEvent watchedEvent) {
                try {
                    watcherList();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                } catch (KeeperException e) {
                    throw new RuntimeException(e);
                }
            }
        });

    }
}

package com.atguigu.case1;

import org.apache.zookeeper.*;

import java.io.IOException;

/**
 * case 1
 * 服务器动态上下线例子
 * <p>
 * 1. 创建zk连接
 * 2. 注册服务器到zk集群
 * 3. 业务代码(睡觉
 */
public class DistributeServer {

    ZooKeeper zooKeeper;

    public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
        DistributeServer zk = new DistributeServer();
        zk.connect();

        zk.register(args[0]);

        zk.business();
    }

    private void business() throws InterruptedException {
        Thread.sleep(Long.MAX_VALUE);
    }

    private void register(String hostName) throws InterruptedException, KeeperException {
        zooKeeper.create("/servers/"+hostName, hostName.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
        System.out.println(hostName + "已注册上");
    }

    private void connect() throws IOException {
        String connectString = "192.168.88.130:2181,192.168.88.131:2181,192.168.88.132:2181";
        int sessionTimeout = 3000000;
        zooKeeper = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
            public void process(WatchedEvent watchedEvent) {
            }
        });
    }


}

五、ZooKeeper分布式锁案例

在这里插入图片描述

package com.atguigu.case2;

import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;

import java.io.IOException;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;

/**
 * 分布式锁
 */
public class DistributedLock {

    public ZooKeeper zooKeeper;
    public CountDownLatch connectLatch = new CountDownLatch(1);
    public CountDownLatch waitLatch = new CountDownLatch(1);
    private String waitPath;
    private String currentNode;

    DistributedLock() throws IOException, InterruptedException, KeeperException {
        //连接zk
        String connectString = "192.168.88.130:2181,192.168.88.131:2181,192.168.88.132:2181";
        int sessionTimeout = 3000;
        zooKeeper = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
            public void process(WatchedEvent watchedEvent) {
                //连接完成后释放connectLatch
                if (watchedEvent.getState() == Event.KeeperState.SyncConnected) {
                    connectLatch.countDown();
                }
                //当前锁节点为最小锁时,释放waitLatch
                if (watchedEvent.getType() == Event.EventType.NodeDeleted && watchedEvent.getPath().equals(waitPath)) {
                    waitLatch.countDown();
                }
            }
        });
        //连接完成后继续执行
        connectLatch.await();
    }

    public void lock() throws InterruptedException, KeeperException {
        // 检测locks节点是否存在,不存在就建一个
        Stat exists = zooKeeper.exists("/locks", false);
        if (exists == null){
            zooKeeper.create("/locks",null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        }
        //创建锁节点
        currentNode = zooKeeper.create("/locks/res-",null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);

        // 判断是否是头一个,是的话给锁
        List<String> locks = zooKeeper.getChildren("/locks", false);
        Collections.sort(locks);

        //若数组内无值,说明就是第一位可以直接给锁
        if (locks.size() == 0){

        }else {
            //算出创建锁的位置,判断是否是最小的,是的话就给锁,否则对上一个锁进行监听
            int location = locks.indexOf(currentNode.substring("/locks/".length()));
            if (location == 0){
                //最小给锁

            }else if (location == -1){
                //错误
                System.out.println("错误");
            }else {
                waitPath = locks.get(location - 1);
                zooKeeper.getData(waitPath,true,null);

                //等待监听
                waitLatch.await();
            }
        }

    }

    public void unlock() throws InterruptedException, KeeperException {
        zooKeeper.delete(currentNode,-1);
    }
}

package com.atguigu.case2;

import org.apache.zookeeper.KeeperException;

import java.io.IOException;

public class Client {
    public static void main(String[] args) throws IOException, InterruptedException, KeeperException {

        new Thread(new Runnable() {
            public void run() {
                try {
                    DistributedLock distributedLock = new DistributedLock();
                    distributedLock.lock();
                    System.out.println("线程1启动,获取锁");
                    Thread.sleep(5 * 1000);
                    distributedLock.unlock();
                    System.out.println("线程1释放锁");
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                } catch (KeeperException e) {
                    throw new RuntimeException(e);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }).start();

        new Thread(new Runnable() {
            public void run() {
                try {
                    DistributedLock distributedLock = new DistributedLock();
                    distributedLock.lock();
                    System.out.println("线程2启动,获取锁");
                    Thread.sleep(5 * 1000);
                    distributedLock.unlock();
                    System.out.println("线程2释放锁");
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                } catch (KeeperException e) {
                    throw new RuntimeException(e);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }).start();
    }
}

5.1、分布式锁-成熟框架curator

在这里插入图片描述

六、企业面试真题

EPOCH:leader任期
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/204226.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

分享:大数据方向学生学徒参与条件

学生学徒制的实施旨在解决当前新技术企业招聘技能人才难和青年就业难的结构性矛盾&#xff0c;通过生态链链主企业携手院校共同解决毕业年度学生就业问题&#xff0c;按照学生个人意愿&#xff0c;建立以就业导向的学生学徒制关系&#xff0c;签订学徒培养协议确定学生就业岗位…

采购业务中的组织概述

目录 一、采购和库存管理中组织单位的概览二、企业的组织结构三、采购中组织结构3.1采购组织3.2采购组 一、采购和库存管理中组织单位的概览 1、 客户端&#xff1a;在SAP ERP系统中&#xff0c;客户端通过三位数字定义&#xff0c;并代表这独立的数据记录和独立的业务流程。客…

【带头学C++】----- 九、类和对象 ---- 9.1 类和对象的基本概念----(9.1.4---9.1.6)

目录 9.1.4 设计立方体类 ​编辑 9.1.5 成员函数在类的外部实现 9.1.6 类在其他源文件的实现步骤&#xff08;实现类在不同文件的实现&#xff0c;后续引出构造函数&#xff09; 注意:类定义在同文件testclass.h中&#xff0c;而testclass.cpp是用来实现&#xff08;声明&…

JAVA基础进阶(三)

一、权限修饰符的访问权限 需要特别注意的是: 被private修饰的成员变量以及成员方法只能在本类中进行调用&#xff0c;所以在其他类中创建本类对象,无法直接访问私有成员变量和成员方法,只能通过set、get方法间接访问。被public修饰的成员变量以及成员方法可以在任意地方被调用…

CHEM 14 not know

Goals of this lab: • Create and use a calibration curve for the absorbance/concentration relationship for crystal violet • Evaluate absorbance versus time measurements to determine the order of a reaction • Analyze graphs of data to determine best linea…

微信小程序自定义tabber凸起

一、实现效果 二、下载地址 下载地址 源码有错自己修改一下就行

Jmeter之压力测试总结!

一、基本概念 1.线程组N&#xff1a;代表一定数量的并发用户&#xff0c;所谓并发就是指同一时刻访问发送请求的用户。线程组就是模拟并发用户访问。 2.Ramp-Up Period(in seconds)&#xff1a;建立所有线程的周期&#xff0c;就是告诉jmeter要在多久没启动所有线程&#xff…

JMeter 常见易错问题

1、配置错误&#xff1a; 问题&#xff1a;线程组配置错误&#xff0c;例如设置了错误的线程数或循环次数。 解决方法&#xff1a;检查线程组的配置。确保线程数&#xff08;即并发用户数量&#xff09;设置正确&#xff0c;以及循环次数符合预期。如果要模拟不同类型的用户行…

CAS原理详解

文章目录 1. 问题引入2. CAS底层详解1. Java中CAS实现2. CAS源码分析3. CAS操作存在的缺陷4. ABA问题及其解决方案 1. 问题引入 见下面代码 public class Main {private volatile static int sum0;public static void main(String[] args) throws InterruptedException {for …

TZOJ 1376 母牛的故事(递推和递归)

答案1&#xff08;递推&#xff09;&#xff1a; #include<stdio.h> int main() {int n0,i0;int a[55] { 0,1,2,3,4 }; //数组下标就相当于过了几年&#xff0c;以第四年母牛生出的第一只小母牛成年为周期&#xff0c;初始化前四年的值while (scanf("%d", …

【Docker】Swarm的overlay网络

对于理解swarm的网络来讲&#xff0c;个人认为最重要的两个点&#xff1a; 第一是外部如何访问部署运行在swarm集群内的服务&#xff0c;可以称之为入方向流量&#xff0c;在swarm里我们通过ingress来解决。 第二是部署在swarm集群里的服务&#xff0c;如何对外进行访问&…

Linux环境搭建(Ubuntu22.04)+ 配置共享文件夹(Samba)

Linux开发环境准备 搭建Linux开发环境所需要的软件如下&#xff1a; VMware虚拟机&#xff1a;用于运行Linux操作系统的虚拟机软件之一&#xff0c;VMware下载安装在文章中不做说明&#xff0c;可自行百度谢谢Ubuntu光盘镜像&#xff1a;用于源代码编译&#xff0c;有闲置计算…

自己的测试技术烂, 不学几招怎么能快速提升自己!

很多小伙伴在成功入职后, 进入测试开发发展后, 都会进入一个瓶颈过渡期, 当然能够自己意识到这个问题说明还来得及&#xff01; 那么作为测试开发人员, 如何走出舒适区, 需要学习和掌握那些内容, 从而实现自己的最终目标呢?今天我们就来说一说, 在职场中如何不断的提升自己. …

【Android Studio学习】第一篇、制作一个拥有登录和注册功能的简易APP

目录 第一部分、前言 1、目标效果 2、准备知识 第二部分、详细步骤 1、新建Empty工程 ​2、添加资源文件 3、搭建注册界面 4、搭建登录界面 5、编写注册界面和登录界面的代码 6、设置APP初始界面 7、连接手机&#xff0c;编译工程 第三部分、总结 1、参考资料 2、…

Java+SSM+MySQL基于微信小程序的商城购物小程序(附源码 调试 文档)

基于微信小程序的商城购物小程序 一、引言二、国内外研究现状三、系统设计四、系统实现五、测试与评估六、结论七、界面展示八、源码获取 摘要&#xff1a; 本文介绍了一种基于微信小程序的商城购物小程序&#xff0c;该系统分为管理员和用户两种用户角色。管理员可以通过系统进…

LeetCode 7 整数反转

题目描述 整数反转 给你一个 32 位的有符号整数 x &#xff0c;返回将 x 中的数字部分反转后的结果。 如果反转后整数超过 32 位的有符号整数的范围 [−2^31, 2^31 − 1] &#xff0c;就返回 0。 假设环境不允许存储 64 位整数&#xff08;有符号或无符号&#xff09;。 示…

Mac电脑版程序创建工具 VMware InstallBuilder Enterprise mac最新

VMware InstallBuilder Enterprise 是一款功能强大、操作简单、跨平台支持的软件安装和部署工具&#xff0c;可以让开发者更加高效地创建和部署软件&#xff0c;并提供了丰富的功能和工具&#xff0c;适用于不同的用户需求和场景。 内置调试器 轻松排除应用程序安装过程中的故…

探索H5的神秘世界:测试点解析

Html5 app实际上是Web app的一种&#xff0c;在测试过程中可以延续Web App测试的部分方法&#xff0c;同时兼顾手机端的一些特性即可&#xff0c;下面帮大家总结下Html5 app 相关测试方法&#xff01; app内部H5测试点总结 1、业务逻辑 除基本功能测试外&#xff0c;需要关注的…

数据中心布线解决方案比较: DAC 电缆和 AOC 光缆

在当今的数字时代&#xff0c;数据中心是无数行业的支柱&#xff0c;它确保了信息的交换并维护关键数据的完整性。为了保持这些数据中心高效运行&#xff0c;选择正确的布线解决方案至关重要。在这方面&#xff0c;两种流行的选择是直连铜缆 (DAC) 和有源光缆 (AOC)。在本文中&…

前缀和——1314. 矩阵区域和

文章目录 &#x1f3a4;1. 题目&#x1f3a4;2. 算法原理&#x1f3a4;3. 代码实现 &#x1f3a4;1. 题目 题目链接&#xff1a;1314. 矩阵区域和 - 力扣&#xff08;LeetCode&#xff09; 给你一个 m x n 的矩阵 mat 和一个整数 k &#xff0c;请你返回一个矩阵 answer &#…