博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
分布式技术 - Zookeeper详解
阅读量:3897 次
发布时间:2019-05-23

本文共 10809 字,大约阅读时间需要 36 分钟。

1. Zookeeper概述

1.1 概述:

Zookeeper它服务的不是商家和用户,而是应用程序。应用程序注入到 Zookeeper中后,Zookeeper就可以为这些应用程序提供服务

  • 淘宝、饿了么、美团等等诸多应用都是 Zookeeper 的现实版本,是一个服务平台,以淘宝为例:
    • 商家必须入驻淘宝,这样淘宝用户才能看到店铺
    • 客户看商品,下订单购买,付款完成交易,一整套流程都是在淘宝这个服务平台上完成的。( 和商家实际上接触并不多 )
  • Zookeeper 是一个开源分布式( 多台服务器干一件事 ) ,并且为分布式应用提供协调服务的Apache项目

1.2 工作机制

  • 从设计模式角度上来看:zookeeper是基观察者模式设计的分布式服务管理框架

    • 观察者模式:简单来说,就是一个监督者监视所有对象,当一个对象被修改时,则会自动通知依赖它的对象
    • Zookeeper:简单来说,Zookeeper对于每一个入驻的服务/程序进行监听,如果哪一个服务下线/上线,将通知客户端应用程序
  • 负责存储管理,一些大家都关心的数据。然后接受 观察者(类似淘宝客户) 的注册,一旦这些数据发生变化,Zookeeper通知已经注册的那些观察者做出相应的反应。从而实现集群中类似的 主从管理模式

  • Zookeeper = 文件系统 + 通知机制

1.3 特点

  • 分布式集群

    • 无论分布式还是集群,都是有很多 人(很多台服务器) 再做事情,

    • 例如:饭店招聘

      • 分布式:

        招了1个厨师,3个服务员,1个前台。虽然工作不一样,但是都是为这个饭店的运转工作

      • 集群:

        招聘3个服务员,但是这3个人的工作是一样的,这就是集群

    • 实际运用:

      • 淘宝 = 订单模块 + 用户模块 + 商品模块 + …,这就是分布式。
      • 双十一,订单量巨大,就会新增很多处理订单模块的服务器。这些,新增的服务器都是用处理订单的,就是集群

Feature:

  • zookeeper是 一个leader、多个follower 组成的集群

  • Leader是通过内部选举机制临时产生

    在这里插入图片描述

  • 集群中,只要有半数以上的节点存活,Zookeeper就能正常工作,比如:

    假设有10台服务器:

    • 挂了4台能够正常工作
    • 挂了5台及以上,Zookeeper服务就停止了
  • Zookeeper中的数据,具有全局一致性,每台服务器都保存一分相同的数据副本。无论,客户端连接哪台服务器,数据都是一致的

  • 数据的跟新,具有原子性。要么成功,要么失败

  • 实时性,在一定的时间范围内,客户端都能读取到最新的数据

  • 更新的请求 按照顺序执行,会按照发向服务器请求的顺序,逐一执行

1.4 数据结构

在这里插入图片描述

  • 整体,可以看做是 树状结构 ,每一个节称为:Znode ( ZookeeperNode )
  • 每个Znode默认能够存储 1MB元数据 ,每个Znode的路径都是唯一的
    • 元数据:Metadata,又称中介数据、中继数据,是一种 描述数据的数据 。简单来说,就是记录数据信息的数据

1.5 应用场景

Zookeeper提供了统一命名服务 , 统一配置管理 , 统一集群管理 , 服务器节点动态上下线 , 软负载均衡

1.5.1 统一命名服务

  • 分布式环境下,需要对应用或者服务进行统一命名,便于识别

  • 例如:服务器IP地址不易记住,但是域名很容易记住

    通过域名去访问服务器

在这里插入图片描述

1.5.2 统一配置管理

  • 分布式环境下,每台服务器的配置文件同步是必须的。(如果服务器一多,不可能一台一台的改)
  • 通过Zookeeper进行统一配置管理:
    1. 能够将配置信息,写入到Zookeeper的某个节点上
    2. 每个客户端都会监听这个节点
    3. 一旦节点中的数据被修改,Zookeeper服务会通知没改客户端服务器,进行告知

1.5.3 服务器节点动态上下线

  • 当服务器入驻到Zookeeper后,Zookeeper会对其进行监听。客户端能够实时获取服务器的上下线变化

1.5.4 软负载均衡

  • Zookeeper会记录每台服务器的访问次数,让访问量最小的服务器去处理最新的客户端请求

1.6 下载

在这里插入图片描述

2. 安装:

2.1 本地安装

现将Zookeeper的文件上传到虚拟机的 /opt 目录

2.1.1 解压

# 解压安装包tar -zxvf apache-zookeeper-3.6.0-bin.tar.gz# 查看ll# 解压后的文件名太长,改名为:zookeepermv apache-zookeeper-3.6.0-bin zookeeper# 查看目录ll

2.1.2修改配置文件

# 进入到配置文件夹中cd /opt/zookeeper/conf

修改 zoo_sample.cfg文件,但是不直接修改,复制一份取名为:zoo.cfg,在此文件上修改

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2ohAKhhP-1617932299530)(F:\TyporaNotes\picture\image-20210406150817929.png)]

# 复制 zoo_sample.cfg文件cp zoo_sample.cfg zoo.cfg# 打开 zoo.cfgvim zoo.cfg

打开 zoo.cfg 后,修改配置:

# 存放数据的目录dataDir=/opt/zookeeper/zkData# 存放日志的目录dataLogDir=/opt/zookeeper/zkLog

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fJbMQAs9-1617932299532)(F:\TyporaNotes\picture\image-20210406152327672.png)]

然后 ESC:wq 保存退出

注意:配置后,要在 opt/zookeeper/ 这个目录下,创建 zkDatazkLog 这两个目录

cd /opt/zookeeper# 创建目录mkdir zkDatamkdir zkLog

安装完成

2.2操作Zookeeper

# 进入 Zookeeper安装目录下的 `bin` 目录cd /opt/zookeeper/bin
  1. 启动Zookeeper

    # 启动服务./zkServer.sh start
  2. 查看当前 Zookeeper的启动状态

    ./zkServer.sh status
  3. 查看进程是否启动

jps# 只要有 QuorumPeerMain ,说明Zookeeper启动成功

在这里插入图片描述

  1. 启动客户端

    ./zkCli.sh# 进入客户端后# 查看 所有Zookeeper的所有节点ls /# 退出客户端窗口quit
  2. 停止Zookeeper

    # 停止服务./zkServer.sh stop

2.3 Zookeeper配置文件的参数详解

进入配置文件目录:/opt/zookeeper/conf

zoo_sample.cfg , 但是我们复制了一份:zoo.cfg ,来修改

  1. 查看配置文件

    vim zoo.cfg
    • tickTime = 2000

      • 单位毫秒,是Zookeeper服务器和客户端之间的心跳时间。
      • tickTime = 2000 ,即每隔 2s客户端就往服务器发送一次请求,证明还是联通状态
    • initLimit = 10

      • (集群中的)learder 和 follower 的初始通信时限

      • 集群启动时能容忍的最多心跳数

      • initLimit = 10,即 tickTime * initLimit = 10*2000 ms= 20s,也就是说 20s之内,没有心跳发出,那么视为失效的连接,leader 和 follower 彻底断开

    • syncLimit = 5

      • learder 和 follower 的同步通信时限

      • 集群启动后,learder 和 follower 的最大响应时间

      • 如果超过 syncLimit * tickTime =5*2= 10s,那么 leader认为 follower已经挂掉,leader会将follower从服务器列表删除

    • dataDir = /opt/zookeeper/zkData

      • 存放Zookeeper数据的目录
    • dataLogDir = /opt/zookeeper/zkLog

      • 存放日志文件的目录
    • clientPort = 2181

      • 客户端需要访问Zookeeper的端口号

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-271829qy-1617932299535)(F:\TyporaNotes\picture\image-20210406162336132.png)]

3. Zookeeper内部原理

3.1 选举机制 (面试重点)

  • 半数机制:

    集群中,半数以上的服务器存活,集群可用。所以,Zookeeper适合安装奇数台服务器

  • Leader的选举机制:

    在这里插入图片描述

3.2 节点类型

  • 持久型:

    • 持久化目录节点:客户端和服务器断开连接后,创建的节点依然存在
    • 持久化顺序编号目录节点:客户端和服务器断开连接后,创建的节点依然存在。创建Znode时会设置顺序标识,即在Znode名后附加一个值来标识顺序,例如:Znode001,Znode002…
  • 短暂型:

    • 临时目录节点:客户端和服务器断开连接后,创建的节点会自动删除
    • 零时顺序编号目录节点:客户端和服务器断开连接后,创建的节点会自动删除。创建Znode时会设置顺序标识,即在Znode名后附加一个值来标识顺序,例如:Znode001,Znode002…

    注意:顺序标识的序号,呈 i ++ 的增长。和数据库中自增类似

3.3 监听器原理(面试重点)

在这里插入图片描述

  1. 在main方法中,创建两个线程,一个负责网络通信,一个负责监听
  2. 监听事件会通 过网络通信线程,发送给 Zookeeper
  3. Zookeeper获得注册的监听事件后,立刻将 监听事件 添加到监听列表
  4. 当zookeeper监听到 数据变化或者路径变化就会将这个消息发送监听线程
  5. 就客户端接收到,数据有变后,监听线程就会在内部调用process方法,做出相应操作 ( process的方法需要根据需求,自己实现 )
  • 常见的监听:
    • 监听:子节点增减的变化
    • 监听:节点数据的变化

3.4 写数据的流程

在这里插入图片描述

  1. 客户端发送一个 写入数据的请求(想在 Zookeeper的server1上写入数据)
  2. 如果 server1 不是Leader,那么 server1 会把请求进一步转发给 Leader
  3. 这个 Leader会将写请求的操作,广播给每个server,server写数据操作执行成功后会通知 Leader
  4. Leader接到半数以上的 server 写数据成功的通知,那么写入数据的操作成功
  5. 然后,Leader会告诉 server1写入数据成功
  6. server1通知 客户端,写入数据成功,整个流程结束

4. Zookeeper 实战(开发重点

4.1 分布式安装部署

集群思路:先搞定一台服务器,再克隆出两台,形成3台服务器的集群(3台是最低标准)

4.1.1 安装Zookeeper

略…( 上文有介绍 )

4.1.2 配置服务器编号 - myid

  • /opt/zookeeper/zkData 中创建 myid 文件

    cd /opt/zookeeper/zkData/# 创建myidvim myid# i键进行编辑 (实际上是添加该服务器对应的编号:1 )1# Esc :WQ# 查看myid文件cat myid

4.1.3 修改配置文件

上文是介绍了,配置文件是复制一份并且重名为 zoo.cfg

  • 打开配置文件

    # 进入bin目录 cd /opt/zookeeper/conf# 打开配置文件vim zoo.cfg
  • 修改配置文件:

    # ---------cluster(集群)-----------server.1=192.168.2.17:2888:3888server.2=192.168.2.18.82:2888:3888server.3=192.168.2.19:2888:3888

    参数解读: server.A = B : C : D

    • A:我们之前配置的服务器编号(/opt/zookeeper/zkData/myid 中的值)
    • B:该服务器的IP地址
    • C:与集群中 Leader 服务器交换信息的端口
    • D:选举机制的专用端口 (万一leader服务器宕机,需要该端口来重新选举一个服务器作为 Leader)。该端口在选举时,进行服务器之间的相互通信
  • 查看配置文件是否修改成功:

    cat /opt/zookeeper/conf/zoo.cfg

4.1.4 配置其余两台服务器

  1. 找到存放虚拟机数据的目录 (D:\Program Files\vm

    在这里插入图片描述

  2. D:\Program Files\vm 目录下创建 zk02 文件夹

  3. 将我们刚刚配置好的服务器数据目录中 所有的.vmx文件和.vmdk文件分别拷贝到 zk02 文件夹

    在这里插入图片描述

  4. 打开 虚拟机 —> 文件 —> 打开 ( 选择zk02下的 .vmx文件 )

  5. 开启虚拟机后,弹出对话框,选择 我已复制该虚拟机

  6. 进入系统后:

    • 修改Linux中的 IP地址
    • 修改 /opt/zookeeper/zkData/myid 为 2
    • 测试网是否能通: ping www.baidu.com
  7. 同理,按照相同的操作配置另外的服务器

4.1.5 集群操作

  1. 关闭每台服务器的防火墙

    • 防火墙的状态:

      • Active: active (running):开启
      • Active: inactive (dead):关闭
    • 常用命令:

      # 查看防火墙systemctl status firewalld# 开启防火墙systemctl start firewalld.service# 关闭防火墙systemctl stop firewalld.service# 设置开机自动启动防火墙systemctl enable firewalld.service# 关闭开机制动启动防火墙systemctl disable firewalld.service# 在不改变状态的条件下重新加载防火墙firewall-cmd --reload
  2. 关闭防火墙之后,启动第一台服务器

    # 进入bin目录cd /opt/zookeeper/bin/# 启动服务./zkServer.sh start
  3. 查看启动状态

    cd /opt/zookeeper/bin/ # 查看状态./zkServer.sh status

    会发现有一个Error

    在这里插入图片描述

  4. 注意:当启动两台服务器时,查看状态:

    • 第一台:mode: follower
    • 第二台:mode: leader

4.2 客户端命令行

  1. 启动客户端 ( Server1: 服务器编号为1 )

    cd /opt/zookeeper/bin# 启动./zkCli.sh
  2. 显示所有操作命令:help

  3. 查看Znode中的所有内容:ls + path

    # 查看根目录下有哪些Znodels /
  4. 查看当前节点的详细数据:ls -s + path

    # 查看根节点的详细数据ls -s /
  5. 创建普通节点:create

    # 在根目录下创建USAcreate /USAcreate /UK
  6. 在更目录/ 下创建,俄罗斯节点,并保存“普京” 数据到节点上

    create /Ru "pujing"
  7. 创建多级节点:

    • 在日本节点下,创建 东京节点(这时候日本节点必须存在,提前创建好,不然报错)
    # 先创建日本节点create /japan# 再在日本节点下, 创建东京节点create /japan/Tokyo
  8. 获得节点的值:get

    get /Ru
  9. 创建临时节点(断开连接后,删除): create -e

    create -e /YiLaKe
  10. 创建带序号的节点:create -s

    # 创建持久的顺序节点create -s /USA/city	# 执行3次# 创建临时的顺序节点create -s -e /USA/city
  11. 修改节点中的值:set

    set /japan/Tokyo-1
  12. 监听节点的值变化子节点变化

    • 在server3服务器上,注册监听/USA的变化

      addwatch /USA
    • 在Server1 主机上修改/USA的数据

      set /USA "hot"
    • Server3会立刻响应:

      WatchedEvent state:SyncConnected type:NodeDataChanged path:/USA

    • 如果在Server1 的/USA下创建子节点 NewYork,Server3会立刻响应

      WatchedEvent state:SyncConnected type:NodeCreated path:/USA/NewYork

  13. 删除:delete

  14. 递归参数:deleteall

    deleteall /USA

4.3 API应用

4.3.1 IDEA环境的搭建

  • 创建maven项目

  • 导入依赖

    org.apache.logging.log4j
    log4j-core
    2.13.3
    org.apache.zookeeper
    zookeeper
    3.6.0
    junit
    junit
    4.12
  • 在resource目录下创建 log4j.properties

     

4.3.2 创建Zookeeper对象

其实就是创建Zookeeper的客户端

public ZooKeeper(    String connectString,    int sessionTimeout,     Watcher watcher)

参数详解:

  • connectStringip:port这种格式,多个的话用逗号,隔开(不能有空格)
  • sessionTimeout
    • 一般设置60*1000,就是60s
    • 一定不能太小。因为Zookeeper加载集群环境,会因为性能等原因而延迟过高。如果设置过小,在没有创建好客户端,就会操作节点,发生空指针异常
  • watcher
    • Watcher是一个监听器接口,但是这里需要的是 对象,所以用匿名内部类
    • 要重写process方法:客户端收到监听信息后,会在内部调用process方法,做出相应操作
public class TestZK {
private String connectString = "192.168.2.17:2181," + "192.168.2.18:2181," + "192.168.2.19:2181"; private int sessionTimeout = 120 * 1000; /** * 客户端对象 */ private ZooKeeper zkClient; @Test public void init() throws Exception{
zkClient=new ZooKeeper(connectString, sessionTimeout, new Watcher() {
public void process(WatchedEvent watchedEvent) {
System.out.println("监听到,并且正在处理"); } }); }}

4.3.3 创建节点

// create方法, 客户端对象调用public String create(    String path,     byte[] data,     List
acl, CreateMode createMode)

参数详解:

  • path:节点路径
  • data: 节点存储的内容 (byte字节的数组,可以把StringgetBytes方法转换)
  • acl:节点的权限
    • 一个ACL就是一个 id-permission对,类似于 key-value 键值对
    • permission:是一个int表示的位码,每一位代表一种操作对应的允许状态,类似于Linux的文件权限,不同的是共有5种操作:CREATEREADWRITEDELETEADMIN(admin 对应更改ACL权限)
      • OPEN_ACL_UNSAFE:创建开放节点,允许任意操作 (常用)
      • READ_ACL_UNSAFE:创建自读节点
      • CREATOR_ALL_ACL:创建者才有全部权限
  • createMode:创建节点的类型,比如:持久型的,还是临时节点
    • CreateMode.PERSISTENT:持久节点
    • CreateMode.PERSISTENT_SEQUENTIA:持久带序号的节点
    • CreateMode.EPHEMERAL:临时节点
    • CreateMode.EPHEMERAL_SEQUENTIAL:临时带序号的节点
// 创建节点String str = zkClient.create(    "/usa",    "要存储的数据".getBytes(),     ZooDefs.Ids.OPEN_ACL_UNSAFE,    CreateMode.PERSISTENT);

然后在服务端查看:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mLYiEgJY-1617932299543)(F:\TyporaNotes\picture\image-20210407180633868.png)]

节点创见成功

4.3.4 获取节点数据

public byte[] getData(    String path,    boolean watch,     Stat stat)

参数详解:

  • String path:想要获取数据的节点的路径
  • boolean watch:是用来注册的通知接口,如果节点发生变更,就会通过当前的接口通知客户端。
  • Stat stat:是用来描述该数据节点的状态信息
// 获取数据byte[] data = zkClient.getData("/usa", false, new Stat());// 将获取到的数据,转为StringString str = new String(data);

4.3.4 修改节点:

public Stat setData(    String path,    byte[] data,    int version)

参数详解:

  • String path:要修改的目标节点
  • byte[] data:修改的内容
  • int version:版本号 (在服务器上用: ls -s 查看)
// 修改 /usa 节点上的数据 Stat stat = zkClient.setData(     "/usa",      "usa节点的值已修改".getBytes(),      0 );

4.3.5 删除节点

public void delete(String path, int version)

参数详解:

  • String path:要删除的目标节点
  • int version:版本号 (在服务器上用: ls -s 查看)
zkClient.delete("/usa", 1);

4.3.6 获取子节点

public List
getChildren(String path, boolean watch)

参数详解:

  • String path:目标节点路径
  • boolean watch: 监听还是不监听

返回值:

  • List<String>:目标节点的所有子节点集合
List
list = zkClient.getChildren("/USA", false);

4.3.7 节点的监听

和获取字节点的方法一样,值时参数 watch为true,变为了监听状态

// 监听根节点List
list = zkClient.getChildren("/", true);

如果 /目录下,有节点发生变化,就会被监听到,调用内部的 process 方法。 process 方法在我们创建 Zookeeper对象时就会定义

4.3.8 节点的判断

public Stat exists(String path, boolean watch)

例子:

Stat stat = zkClient.exists("/YiLaKe", false);// 判断if (stat==null){
System.out.println("节点不存在");}else {
System.out.println("节点存在");}

4.4 实战模拟 — 美团商家的上下线

4.4.1 需求分析

  • 模拟美团的服务平台

    • 商家营业通知
    • 商家打烊通知
  • 提前在更节点下,创建好/meituan 节点

4.4.2 代码

1. pom文件的配置

同 4.3.1…

2. 商家服务类

…待跟新

3. 客户类

…待跟新

转载地址:http://yhuen.baihongyu.com/

你可能感兴趣的文章
Ubuntu安装NVIDIA显卡驱动
查看>>
vue-cli中实现dolist
查看>>
sass的安装
查看>>
Vue-cli中路由配置
查看>>
豆瓣高分JAVA书籍,你都读过吗?
查看>>
java图书管理系统
查看>>
C#图书管理系统
查看>>
C#酒店管理系统
查看>>
你对ArrayList了解多少?
查看>>
《从Paxos到ZooKeeper分布式一致性原理与实践》学习知识导图
查看>>
Java基础面试题(一) (2020持续更新)
查看>>
JAVA人事管理系统
查看>>
Dubbo面试题(关注小R持续更新)
查看>>
JAVA仿微博系统(JAVA毕业设计含源码和运行教程)
查看>>
24BITBMP位图的文件结构及创建
查看>>
如何在自定义控件中获得width和height?
查看>>
Android UI开发专题之界面设计【基础API】
查看>>
ejarmaker: jar 、java类的加密工具
查看>>
配置NFS实现Linux服务器之间的文件共享
查看>>
PostgreSQL连接池pgbouncer的使用
查看>>