Zookeeper从零入门笔记

news2024/12/24 5:48:03

Zookeeper从零入门笔记

  • 一、入门
    • 1. 概述
    • 2. 特点
    • 3. 数据结构
    • 4. 应用场景
  • 二、本地
    • 1.安装
    • 2. 参数解读
  • 三、集群操作
    • 3.1.1 集群安装
    • 3.2 选举机制
      • 1. 第一次启动
      • 2. 非第一次启动
    • 3.3 ZK集群启动停止脚本
    • 3.4 客户端命令行操作
      • 3.2.1 命令行语法
      • 3.2.2 节点类型(持久/短暂/有序号/无序号)
      • 3.2.4 监听器原理
      • 3.3 删除节点
    • 3.5 客户端API操作
    • 3.6 监听节点变化
    • 3.7 判断Znode是否存在
    • 3.8 写数据原理
  • 四、服务器动态上下线监听案例
  • 五、ZooKeeper分布式锁案例
    • 5.1、分布式锁-成熟框架curator
  • 六、企业面试真题

一、入门

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任期
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

飞致云开源社区月度动态报告(2023年11月)

自2023年6月起&#xff0c;中国领先的开源软件公司FIT2CLOUD飞致云以月度为单位发布《飞致云开源社区月度动态报告》&#xff0c;旨在向广大社区用户同步飞致云旗下系列开源软件的发展情况&#xff0c;以及当月主要的产品新版本发布、社区运营成果等相关信息。 飞致云开源大屏…

传统算法:使用 Pygame 实现选择排序

使用 Pygame 模块实现了选择排序的动画演示。首先,它生成一个包含随机整数的数组,并通过 Pygame 在屏幕上绘制这个数组的条形图。接着,通过选择排序算法对数组进行排序,动画效果可视化每一步的排序过程。在排序的过程中,程序找到未排序部分的最小元素,并将其与未排序部分…

如何获取阿里巴巴中国站按图搜索1688商品(拍立淘) API接口(item_search_img-按图搜索1688商品(拍立淘))

一、背景介绍 阿里巴巴中国站作为中国领先的B2B电子商务平台&#xff0c;提供了大量的商品信息和交易服务。其中&#xff0c;按图搜索1688商品&#xff08;拍立淘&#xff09;是阿里巴巴中国站特有的功能之一&#xff0c;它可以通过上传图片来搜索与图片相似的商品&#xff0c…

Js页面录屏切片存储数据上传后端

前端 screenShot(){// 获取屏幕共享流navigator.mediaDevices.getDisplayMedia({video: true,audio: true,//preferCurrentTab 共享本次操作的页面preferCurrentTab: true}).then(async stream > {const mediaRecorder new MediaRecorder(stream, { mimeType: video/webm; …

基于AT89C51单片机的秒表设计

1&#xff0e;设计任务 利用单片机AT89C51设计秒表&#xff0c;设计计时长度为9:59:59&#xff0c;超过该长度&#xff0c;报警。创新&#xff1a;设置重启&#xff1b;暂停&#xff1b;清零等按钮。最后10s时播放音乐提示。 本设计是采用AT89C51单片机为中心&#xff0c;利用其…

代码随想录算法训练营第一天 | 704. 二分查找 27. 移除元素

class Solution { public:int search(vector<int>& nums, int target) {int l0;int rnums.size()-1;while(l<r){int mid(lr)>>1;if(targetnums[mid]) return mid;if(target>nums[mid]){lmid1;}else{rmid-1;}}return -1;} }; 之前就已经熟悉二分法了&am…

【Linux】第二十三站:缓冲区

文章目录 一、一些奇怪的现象二、用户级缓冲区三、用户级缓冲区刷新问题四、一些其他问题1.缓冲区刷新的时机2.为什么要有这个缓冲区3.这个缓冲区在哪里&#xff1f;4.这个FILE对象属于用户呢&#xff1f;还是操作系统呢&#xff1f;这个缓冲区&#xff0c;是不是用户级的缓冲区…

Linux实现类似cp的命令

1.利用主函数的三个函数进行传参 1).主函数的三个参数的含义: argc:主函数的参数个数 argv:主函数的参数内容 envp:环境变量; 2).演示代码: #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(int argc,char *argv[],char *envp[]…

Vue3.x 中 hooks 函数封装和使用

一、hooks 是什么 vue3 中的 hooks 就是函数的一种写法&#xff0c;就是将文件的一些单独功能的 js 代码进行抽离出来进行封装使用。 它的主要作用是 Vue3 借鉴了 React 的一种机制&#xff0c;用于在函数组件中共享状态逻辑和副作用&#xff0c;从而实现代码的可复用性。 注…

[笔记]dubbo发送接收

个人笔记 consumer 主要使用ThreadlessExecutor实现全consumer的全双工通讯。consumer创建本次请求的requestId用于将response和request匹配。 然后分以下几步完成一次请求发送并接收结果&#xff1a; 槽&#xff1a;发送消息前将用于接收结果的executor放到一个map中存储 发…

AI落地现状:没有mission、业务零碎、连2B还是2C都在摇摆

最近我私下问某TOP AI 2.0公司的核心产品负责人&#xff0c;你们现在主要是2C还是2B&#xff1f; 他说的第一句话是&#xff0c;“整体没有misson”。 结合近期的各种信息&#xff0c;给大家说下行业最前沿的内幕。 1、据说&#xff0c;某1、2位大佬的AI认知&#xff0c;其实并…

最大公约数的C语言实现xdoj31

时间限制: 1 S 内存限制: 1000 Kb 问题描述: 最大公约数&#xff08;GCD&#xff09;指某几个整数共有因子中最大的一个&#xff0c;最大公约数具有如下性质&#xff0c; gcd(a,0)a gcd(a,1)1 因此当两个数中有一个为0时&#xff0c;gcd是不为0的那个整数&#xff…

Linux的dev/vda1文件满了导致MySQL无法写入

其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一、dev/vda1文件介绍 二、排查过程 三、总结 前言 今天查看两个月前上线的小项目&#xff0c;发现运行非常慢&#xff0c;而且增…

正则表达式及文本三剑客grep sed awk

正则表达式 1.元字符 . //匹配任意单个字符&#xff0c;可以是个汉字 [yang] //匹配范围内的任意单个字符 [^y] //匹配处理指定范围外的任意单个字符 [:alnum:] //字母和数字 [:alpha:] //代表…

周报:css相关扩展知识

目录 1. 扩展知识&#xff1a;浮动盒子的排列位置 浮动盒子常见排列特点&#xff1a; 浮动盒子扩展特点&#xff1a; 2.扩展知识:行高的取值 line-height常见取值&#xff1a; 行高的取值的方式&#xff1a; 两个方式的区别&#xff1a; 3.扩展知识&#xff1a;body背景…

无公网IP环境如何远程访问本地内网搭建的Emby影音库服务器

文章目录 1.前言2. Emby网站搭建2.1. Emby下载和安装2.2 Emby网页测试 3. 本地网页发布3.1 注册并安装cpolar内网穿透3.2 Cpolar云端设置3.3 Cpolar内网穿透本地设置 4.公网访问测试5.结语 1.前言 在现代五花八门的网络应用场景中&#xff0c;观看视频绝对是主力应用场景之一&…

kubeadm快速搭建k8s高可用集群

1.安装及优化 1.1基本环境配置 1.环境介绍 &#xff08;1&#xff09;.高可用集群规划 主机名ip地址说明k8s-master01192.168.2.96master节点k8s-master02192.168.2.97master节点k8s-master03192.168.2.98master节点k8s-node01192.168.2.99node节点k8s-node02192.168.2.100n…

uc_12_进程间通信IPC_有名管道_无名管道

1 内存壁垒 进程间天然存在内存壁垒&#xff0c;无法通过交换虚拟地址直接进行数据交换&#xff1a; 每个进程的用户空间都是0~3G-1&#xff08;32位系统&#xff09;&#xff0c;但它们所对应的物理内存却是各自独立的。系统为每个进程的用户空间维护一张专属于该进程的内存映…

JavaWeb服务器详解和后端分层解耦

JavaWeb HTTP协议请求数据格式响应数据格式协议解析 Web服务器请求响应请求参数的接收响应 分层解耦IOC&DI入门IOC详解 HTTP协议 超文本传输协议&#xff0c;规定了浏览器和服务器之间数据传输的规则 特点&#xff1a; 基于TCP协议&#xff1a;面向连接&#xff0c;安全 …

第三方实验室LIMS管理系统源码,asp.net LIMS源码

LIMS实验室信息管理系统源码 LIMS系统的功能根据实验室的规模和任务而有所不同&#xff0c;其系统主要功能包括:系统维护、基础数据编码管理&#xff0c;样品管理、数据管理、报告管理、报表打印、实验材料管理、设备管理等。它可以取代传统的手工管理模式而给检测实验室带来巨…