一、Zookeeper介绍

1、什么是Zookeeper

Zookeeper 是一种分布式协调服务,用于管理大型主机。在分布式环境中协调和管理服务是一个复杂的过程,ZooKeeper通过其简单的架构和API解决了这个问题。ZooKeeper 能让开发人员专注于核心应用程序逻辑,而不必担心应用程序的分布式特性。

2、Zookeeper的应用场景

  • 分布式协调组件

在分布式系统中,需要有zookeeper作为分布式协调组件,协调分布式系统中的状态

  • 分布式锁

zk在实现分布式锁上,可以做到强一致性,关于分布式锁的相关知识,会在之后的ZAB协议中介绍

  • 无状态化的实现


二、搭建ZooKeeper服务器

1、zoo.conf配置文件说明

Zookeeper_数据

2、Zookeeper服务器的操作命令

重命名conf中的文件zoo_sample.cfg->zoo.cfg

重启zk服务器:

./bin/zkServer.sh start ../conf/zoo.cfg

查看zk服务器的状态:

./bin/zkServer.sh status ../conf/zoo.cfg

停止服务器:

./bin/zkServer.sh stop ../conf/zoo.cfgs

三、Zookeeper内部的数据模型

1、zk是如何保存数据的

zk中的数据是保存在节点上的,节点就是znode,多个znode之间构成一棵树的目录结构。

Zookeeper的数据模型是什么样子呢?类似于数据结构中的树,同时也很像文件系统的目录


树是由节点所组成,Zookeeper的数据存储也同样是基于节点,这种节点叫做Znode,但是不同于树的节点,Znode的引用方式是路劲引用,类似于文件路径:

/动物/猫
/汽车/宝马

这样的层级结构,让每一个Znode的节点拥有唯一的路径,就像命名空间一样对不同信息做出清晰的隔离。

2、zk中的znode是什么样的数据结构

zk中的znode包含了四个部分

data:保存数据

acl:权限:

  • c:create 创建权限,允许在该节点下创建子节点
  • w:write 更新权限,允许更新该节点的数据
  • r:read 读取权限,允许读取该节点的内容以及子节点的列表信息
  • d:delete 删除权限,允许删除该节点的子节点信息
  • a:admin 管理者权限,允许对该节点进行acl权限设置

stat:描述当前znode的元数据

child:当前节点的子节点

3、zk中节点znode的类型

1、持久节点:创建出的节点,在会话结束后依然存在。保存数据

2、持久序号节点:创建出的节点,根据先后顺序,会在节点之后带上一个数值,越后执行数值越大,适用于分布式锁的应用场景-单调递增

3、临时节点:临时节点是在会话结束后,自动被删除的,通过这个特性,zk可以实现服务注册与发现的效果。


4、临时序号节点:跟持久序号节点相同,适用于临时的分布式锁

5、Container节点(3.5.3版本新增):Container容器节点,当容器中没有任何子节点,该容器节点会被zk定期删除

TTL节点:可以指定节点的到期时间,到期后被zk定时删除。只能通过系统配置zookeeper.extendedTypeEnablee=true开启

4、zk的数据持久化

zk的数据是运行在内存中,zk提供了两种持久化机制:

事务日志

zk把执行的命令以日志形式保存在dataLogDir指定的路径中的文件中(如果没有指定dataLogDir,则按照 dataDir指定的路径)。

数据快照

zk会在一定的时间间隔内做一次内存数据快照,把时刻的内存数据保存在快照文件中。

zk通过两种形式的持久化,在恢复时先恢复快照文件中的数据到内存中,再用日志文件中的数据做增量恢复,这样恢复的速度更快。

四、Zookeeper客户端(zkCli)的使用

1、多节点类型创建

  • 创建持久节点
    create path [data] [acl]
  • 创建持久序号节点
    create -s path [data] [acl]
  • 创建临时节点
    create -e path [data] [acl]
  • 创建临时序号节点
    create -e -s path [data] [acl]
  • 创建容器节点
    create -c path [data] [acl]

2、查询节点

  • 普通查询
  • ls [-s -R] path
    -s 详细信息
    -R 当前目录和子目录中的所有信息
  • 查询节点相关信息
  • cZxid:创建节点的事务ID
  • mZxid:修改节点的事务ID
  • pZxid:添加和删除子节点的事务ID
  • ctime:节点创建的时间
  • mtime:节点最近修改的时间
  • dataVersion:节点内数据的版本,每更新一次数据,版本会+1
  • aclVersion:此节点的权限版本
  • ephemeralOwner:如果当前节点是临时节点,该是是当前节点所有者的session id。如果节点不是临时节点,则该值为零
  • dataLength:节点内数据的长度
  • numChildren:该节点的子节点个数
  • 查询节点的内容
  • get [-s] path
    -s 详细信息

3、删除节点

  • 普通删除
  • 乐观锁删除
  • delete [-v] path
    -v 版本
  • deleteall path [-b batch size]

3、权限设置

  • 注册当前会话的账号和密码:

addauth digest xiaowang:123456

  • 创建节点并设置权限(指定该节点的用户,以及用户所拥有的权限s)

create /test-node abcd auth:xiaowang:123456:cdwra

  • 在另一个会话中必须先使用账号密码,才能拥有操作节点的权限

五、Curator客户端的使用

1、Curator介绍

Curator是Netflix公司开源的一套zookeeper客户端框架,Curator是对Zookeeper支持最好的客户端框架。Curator封装了大部分Zookeeper的功能,比如Leader选举、分布式锁等,减少了技术人员在使用Zookeeper时的底层细节开发工作。

2、引入依赖

<!--Curator-->
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-framework</artifactId>
    <version>2.12.0</version>
</dependency>
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-recipes</artifactId>
    <version>2.12.0</version>
</dependency>
<!--Zookeeper-->
<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.7.14</version>
</dependency>

配置curator基本连接信息
curator.retryCount=5
curator.elapsedTimeMs=5000
curator.cnotallow=192.168.200.128:2181
curator.sessinotallow=60000
curator.cnotallow=4000

3、编写配置curator配置类

@Data
@Component
@ConfigurationProperties(prefix = "curator")
public class WrapperZK {
  private int retryCount;

  private int elapsedTimeMs;

  private String connectionString;

  private int sessionTimeoutMs;

  private int connectionTimeoutMs;
}

//引用配置类
@Configuration
public class CuratorConfig {

    @Autowired
    private WrapperZK wrapperZK;

    @Bean(initMethod = "start")
    public CuratorFramework curatorFramework(){
        return CuratorFrameworkFactory.newClient(
            wrapperZK.getConnectionString(),
            wrapperZK.getSessionTimeoutMs(),
            wrapperZK.getConnectionTimeoutMs(),
            new RetryNTimes(wrapperZK.getRetryCount(), wrapperZK.getElapsedTimeMs())
        );
    }

}

4、测试

@Autowired
private CuratorFramework curatorFramework;

@Test
//添加节点
void createNode() throws Exception{
    //添加默认(持久)节点
    String path = curatorFramework.create().forPath("/curator-node");
    //添加临时序号节点
    //String path2 = curatorFramework.create().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath("/curator-nodes", "messageDate".getBytes());
    System.out.println(String.format("curator create node :%s  successfully!", path));
    //      System.in.read();
}

@Test
//获取节点值
void getDate() throws Exception {
    byte[] bttes = curatorFramework.getData().forPath("/curator-node");
    System.out.println("bttes = " + bttes);
}

@Test
//设置节点值
void setDate() throws Exception {
    curatorFramework.setData().forPath("/curator-node", "newMessage".getBytes());
    byte[] bytes = curatorFramework.getData().forPath("/curator-node");
    System.out.println("bytes = " + bytes);
}

@Test
//创建多级节点
void createWithParent() throws Exception {
    String pathWithParent = "/node-parent/sub-node-1";
    String path = curatorFramework.create().creatingParentContainersIfNeeded().forPath(pathWithParent);
    System.out.println(String.format("curator create node :%s success!", path));
}

@Test
//删除节点
void delete() throws Exception {
    String path = "/node-parent";
    //删除节点的同时一并删除子节点
    curatorFramework.delete().guaranteed().deletingChildrenIfNeeded().forPath(path);
}

六、zk实现分布式锁

1、zk中锁的种类:

  • 读锁(读锁共享):大家都可以读。上锁前提:之前的锁没有写锁
  • 写锁(写锁排他):只有得到写锁的才能写。上锁前提:之前没有任何锁

2、zk如何上读锁

  • 创建一个临时序号节点,节点的数据是read,表示是读锁
  • 获取当前zk中序号比自己小的所有节点
  • 判断最小节点是否是读锁
  • 如果不是读锁的话,则上锁失败,为最小节点设置监听。阻塞等待,zk的watch机制会当最小节点发生变化时通知当前节点,再执行第二步的流程
  • 如果是读锁的话,则上锁成功。

Zookeeper_数据_02

3、zk如何上写锁

  • 创建一个临时序号节点,节点的数据是write,表示写锁
  • 获取zk中所有的子节点
  • 判断自己是否是最小的节点:
  • 如果是,则上写锁成功
  • 如果不是,说明前面还有锁,则上锁失败,监听最小节点,如果最小节点有变化,则再执行第二步。


4、羊群效应

如果用上述的上锁方式,只要有节点发生变化,就会触发其他节点的监听事件,这样对zk的压力非常大,而羊群效应,可以调整成链式监听。解决这个问题。

Zookeeper_数据_03


5、Curator实现读写锁

  • 获取读锁

@Test
void testGetReadLock()throws Exception{
    //读写锁
    InterProcessReadWriteLock interProcessReadWriteLock = new InterProcessReadWriteLock(client, "/lock1");
    //获取读锁对象
    InterProcessLock interProcessLock = interProcessReadWriteLock.readLock();
    System.out.println("等待获取读锁对象中...");
    //获取锁
    interProcessLock.acquire();
    for(int i = 1; i <= 100; i ++){
        Thread.sleep(3000);
        System.out.println(i);
    }
    //释放锁
    interProcessLock.release();
    System.out.println("等待释放锁...");
}

  • 获取写锁

@Test
void testGetWriteLock()throws Exception{
    //读写锁
    InterProcessReadWriteLock interProcessReadWriteLock = new InterProcessReadWriteLock(client, "/lock1");
    //获取写锁对象
    InterProcessLock interProcessLock = interProcessReadWriteLock.writeLock();
    System.out.println("等待获取写锁对象中...");
    //获取锁
    interProcessLock.acquire();
    for(int i = 1; i <= 100; i ++){
        Thread.sleep(3000);
        System.out.println(i);
    }
    //释放锁
    interProcessLock.release();
    System.out.println("等待释放锁...");
}

七、zk的watch机制

1、Watch机制介绍

我们可以把Watch理解成是注册在特定Znode上的触发器。当这个Znode发生改变,也就是调用了create,delete,setData方法的时候,将会触发Znode上注册的对应事件,请求Watch的客户端会收到异步通知。

具体交互过程如下:

  • 客户端调用getData方法,watch参数是true。服务端接到请求,返回节点数据,并且在对应的哈希表里插入被Watch的Znode路径,以及Watcher列表。

Zookeeper_客户端_04

  • 当被Watch的Znode已删除,服务端会查找哈希表,找到该Znode对应的所有Watcher,异步通知客户端,并且删除哈希表中对应的key-value。

Zookeeper_zookeeper_05

2、zkCli客户端使用Watch

create /test date
get -w /test  一次性监听节点
ls -w /test   监听目录,创建和删除子节点会收到通知。但是子节点中新增节点不会被监听到
ls -R -w /test  监听子节点中节点的变化,但内容的变化不会收到通知

3、Curator客户端使用Watch

@Test
public void addNodeListener() throws Exception{
    NodeCache nodeCache = new NodeCache(curatorFramework,"/curator-node");
    nodeCache.getListenable().addListener(new NodeCacheListener() {
        @Override
        public void nodeChanged() throws Exception{
            log.info("{} path nodeChanged: ", "/curator-node");
            printNodeData();
        }
    )};
    nodeCache.start();
    //System.in.read();
}

public void printNodeData() throws Exception{
    byte[] bytes = curatorFramework.getData().forPath("/curator-node");
    log.info("data: {}", new String(bytes));
}

八、Zookeeper集群实战

1、Zookeeper集群角色

zookeeper集群中的节点有三种角色

  • Leader:处理集群的所有事务请求,集群中只有一个Leader
  • Follwoer:只能处理读请求,参与Leader选举
  • Observer:只能处理读请求,提升集群读的性能,但不能参与Leader选举


2、集群搭建

搭建4个节点,名字为zk1,zk2,zk3,zk4,其中一个节点为Observer

1)在4个节点中分别创建myid并设值
在usr/local/zookeeper中创建一下四个文件

/usr/local/zookeeper/zkdata/zk1# echo 1 > myid
/usr/local/zookeeper/zkdata/zk2# echo 2 > myid
/usr/local/zookeeper/zkdata/zk3# echo 3 > myid
/usr/local/zookeeper/zkdata/zk4# echo 4 > myid

2)编写4个zoo.cfg

命名为zoo1.cfg,zoo2.cfg,zoo3.cfg,zoo4.cfg;同时修改dataDir和clientPort。

# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial 
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between 
# sending a request and getting an acknowledgement
syncLimit=5
# 四台服务器修改对应的zk1 zk2 zk3 zk4
dataDir=/usr/local/zookeeper/zkdata/zk1
# 四台服务器对应的端口号2181,2182,2183,2184
clientPort=2181

#2001为集群通信端口,3001为集群选举端口,observer(观察者身份)
server.1=192.168.200.128:2001:3001
server.2=192.169.200.128:2002:3002
server.3=192.168.200.128:2003:3003
server.4=192.168.200.128:2004:3004:observer

3)启动四台服务器


3、连接Zookeeper集群

./bin/zkCli.sh -server 192.168.200.128:2181,192.168.200.128:2182,192.168.200.128:2183

九、ZAB协议

1、什么是ZAB协议

zookeeper作为非常重要的分布式协调组件,需要进行集群部署,集群中会以一主多从的形式进行部署。zookeeper为了保证数据的一致性,使用了ZAB(Zookeeper Atomic Broadcast)协议,这个协议解决了Zookeeper的崩溃恢复和主从数据同步的问题。


2、ZAB协议定义的四种节点状态

  • Looking:选举状态
  • Following:Following节点(从节点)所处的状态
  • Leading:Leader节点(主节点)所处状态

3、集群上线Leader选举过程

  1. 半数机制:集群中半数以上机器存活,集群可用。所以 Zookeeper 适合安装奇数台服务器。例如,5台服务器有3台存活,集群可用,而只有2台存活,集群不可用。
  2. Zookeeper 虽然在配置文件中并没有指定 Master 和 Slave。 但是, Zookeeper 工作时,是有一个节点为 Leader,其他则为 Follower, Leader 是通过内部的选举机制临时产生的。

以一个简单的例子来说明整个选举的过程。

假设有五台服务器组成的 Zookeeper 集群,它们的 id 从 1-5,同时它们都是最新启动的,也就是没有历史数据,在存放数据量这一点上,都是一样的。假设这些服务器依序启动,来看看会发生什么,如下图所示。


Zookeeper_数据_06


  1. 服务器 1 启动, 发起一次选举。服务器 1 投自己一票。此时服务器 1 票数一票,不够半数以上(3 票),选举无法完成,服务器 1 状态保持为 LOOKING;
  2. 服务器 2 启动, 再发起一次选举。服务器 1 和 2 分别投自己一票并交换选票信息:此时服务器 1 发现服务器 2 的 ID 比自己目前投票推举的(服务器 1)大,更改选票为推举服务器 2。此时服务器 1 票数 0 票,服务器 2 票数 2 票,没有半数以上结果,选举无法完成,服务器 1, 2 状态保持 LOOKING
  3. 服务器 3 启动, 发起一次选举。此时服务器 1 和 2 都会更改选票为服务器 3。此次投票结果:服务器 1 为 0 票,服务器 2 为 0 票,服务器 3 为 3 票。此时服务器 3 的票数已经超过半数,服务器 3 当选 Leader。服务器 1, 2 更改状态为 FOLLOWING,服务器 3 更改状态为 LEADING;
  4. 服务器 4 启动, 发起一次选举。此时服务器 1, 2, 3 已经不是 LOOKING 状态,不会更改选票信息。交换选票信息结果:服务器 3 为 3 票,服务器 4 为 1 票。此时服务器 4服从多数,更改选票信息为服务器 3,并更改状态为 FOLLOWING;
  5. 服务器 5 启动,同 4 一样当小弟。

Zookeeper_客户端_07

4、崩溃恢复时的Leader选举

Leader建立完后,Leader周期性地不断向Follower发送心跳(ping命令,没有内容的socket)。当Leader崩溃后,Follower发现socket通道已关闭,于是Follower开始进入到Looking状态,重新回到上一节中的Leader选举状态,此时集群不能对外提供服务。

Zookeeper_zookeeper_08

5、主从服务器之间的数据同步

Zookeeper_数据_09

6、Zookeeper中的NIO与BIO的应用

  • NIO
  • 用于被客户端连接的2181端口,使用的是NIO模式与客户端建立连接
  • 客户端开启Watch时,也使用NIO,等待Zookeeper服务器的回调
  • BIO
  • 集群在选举时,多个节点之间的投票通信端口,使用BIO进行通信

十、CAP理论

2000年7月,加州大学伯克利分校的 Eric Brewer教授在ACM PODC会议上提出CAP猜想。2年后,麻省理工学院的Seth Gilbert和 Nancy Lynch 从理论上证明了CAP。之后,CAP理论正式成为分布式计算领域的公认定理。

CAP理论

CAP理论为:一个分布式系统最多只能同时满足一致性(Consistency)、可用性(Availability)和区分容错性(Partition tolerance)这三项中的两项。

  • —致性(Consistency)

一致性指"all nodespsee the same data at the same time",即更新操作成功并返回客户端完成后,所有节点在同一时间的数据完全一致。

  • 可用性(Availability)

可用性指"Reads and writes always succeed",即服务一直可用,而且是正常响应时间。

  • 分区容错性(Partition tolerance)

分区容错性指"the system continues to operate despite arbitrary message loss or failure of part of the system",即分布式系统在遇到某节点或网络分区故障的时候,仍然能够对外提供满足一致性或可用性的服务。——避免单点故障,就要进行冗余部署,冗余部署相当于是服务的分区,这样的分区就具备了容错性。


BASE理论

eBay的架构师Dan Pritchett源于对大规模分布式系统的实践总结,在ACM上发表文章提出BASE理论,BASE理论是对CAP理论的延伸,核心思想是即使无法做到强一致性《Strong Consistency,CAP的一致性就是强一致性),但应用可以采用适合的方式达到最终一致性(Eventual Consitency) 。

  • 基本可用(Basically Available)

基本可用是指分布式系统在出现故障的时候,允许损失部分可用性,即保证核心可用。

电商大促时,为了应对访问量激增,部分用户可能会被引导到降级页面,服务层也可能只提供降级服务。这就是损失部分可用性的体现。

  • 软状态(Soft State)

软状态是指允许系统存在中间状态,而该中间状态不会影响系统整体可用性。分布式存储中一般一份数据至少会有三个副本,允许不同节点间副本同步的延时就是软状态的体现。mysql replication的异步复制也是一种体现。

  • 最终一致性(Eventual Consistency)

最终一致性是指系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。弱一致性和强一致性相反,最终一致性是弱一致性的—种特殊情况。

Zookeeper追求的一致性

Zookeeper在数据同步时,追求的并不是强一致性,而是顺序一致性(事务id的单调递增)


十一、面试题

1、Zookeeper是什么

说一说Zookeeper是什么吧?

ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,主要为了解决分布式架构下数据一致性问题,典型的应用场景有分布式配置中心、分布式注册中心、分布式锁、分布式队列、集群选举、分布式屏障、发布/订阅等场景。

Zookeeper是怎样的一个数据结构呢?

Zookeeper是一个类似于文件系统的数据结构,最外层我们可以想象成一个大的文件夹,里面都是一些小的文件夹。

2、Zookeeper有哪些数据结构

Zookeeper有几种常用的数据格式呢

1、持久化目录节点:

客户端与zookeeper断开连接后,该节点依旧存在,只要不手动删除该节点,他将永远存在。

2、持久化顺序编号目录节点:

客户端与zookeeper断开连接后,该节点依旧存在,只是zookeeper给该节点名称进行顺序编号。

3、临时目录节点:

客户端与zookeeper断开连接后,该节点被删除。

4、临时顺序编号目录节点:

客户端与zookeeper断开连接后,该节点被删除,只是zookeeper给该节点名称进行顺序编号。


3、Zookeeper有哪些核心功能

Zookeeper有哪些核心的功能

zookeeper有监听通知机制,如果对某个节点进行监听,当这个节点被删除,或者被修改时,监听方会感知到修改消息。

zookeeper有监听机制,那么可以监听到几种类型的变化呢?

1、None:连接建立事件

2、NodeCreated:节点创建

3、NodeDeleted:节点删除

4、NodeDataChanged:节点数据变化

5、NodeChildrenChanged:子节点列表变化

6、DataWatchRemoved:节点监听被移除

7、ChildWatchRemoved:子节点监听被移除

开发中使用Synchronized就可以保证线程安全了,为什么还需要使用zookeeper来实现分布式锁呢?

如果我们是单机情况下也就是只有一个进程的情况下使用Synchronized是可以保证线程安全的。但是分布式情况下是多个不同的进程,而不是一个进程里面不同的线程,所以Synchronized是无法保证多个进程安全的。

zookeeper节点有哪些重要信息呢,怎么进行查看?

zookeeper节点可以通过stat命令来查看主要信息,其中信息有:

  1. cZxid:创建znode的事务id(Zxid的值)。
  2. mZxid:最后修改znode的事务id。
  3. pZxid:最后添加或删除子节点的事务id(子节点列表发生变化才会发生改变)。
  4. ctime:znode创建时间。
  5. mtime:znode最近修改时间。
  6. dataVersion:znode的当前数据版本。
  7. cversion:znode的子节点结果集版本(一个节点的子节点增加、删除都会影响这个版本)。
  8. aclVersion:表示对此znode的acl版本。
  9. ephemeralOwner:znode是临时znode时,表示znode所有者的sessionid,如果znode不是临时节点,则该字段设置为零。
  10. 1dataLength:znode数据字段的长度。

zookeeper创建节点,和监听节点有哪些命令?

1、创建持久节点:create /节点名称

2、创建持久顺序节点:create -s /节点名称

3、创建临时节点:create -e /节点名称

4、创建临时顺序节点:create -e -s /节点名称

5、监听节点:get -w /节点名称


4、Zookeeper有哪些权限控制

zookeeper有哪些权限控制呢?

zookeeper有ACL( Access Control List )权限控制,可以控制节点的读写操作,保证数据的安全性,不然的话谁都可以创建和删除节点,那不就乱了套了。

ACL权限设置有几部分组成呢?

有三部分组成,分别是权限模式、授权对象、权限信息。

权限模式:就是zookeeper服务器进行权限验证的方式,比如手机解锁是用指纹还是用密码呢,如果用密码,知道密码的都可以解锁你的手机,如果用指纹,只有你自己的手指头可以解锁。所以权限模式大体分为两种类型:

  • 范围验证: 范围就是zookeeper可以针对一个ip或者一段ip地址授予权限,相当于指纹解锁,我给我一个手指头,或者所有的脚指头都授予权限。
  • 口令验证: 可以理解为用户名密码的方式,这种就相当于密码解锁了,知道了用户名密码后所有的人都相当于授予了权限。

授权对象: 授权对象就是把权限授予给谁,如果是范围验证方式,那么授权对象就是ip地址,如果是口令验证,授权对象就是用户名。

授权信息: 授权信息就是指我们具体的权力是什么,比如我们解锁手机后可以打游戏还是可以听歌,还是可以用手机砸核桃呢。

zookeeper中定义好的权限有5种:

  1. 数据节点(c:create)创建权限,授予权限的对象可以在数据节点下创建子节点。
  2. 数据节点(w:wirte)更新权限,授予权限的对象可以更新该数据节点。
  3. 数据节点(r:read)读取权限,授予权限的对象可以读取该节点的内容以及子节点的列表信息。
  4. 数据节点(d:delete)删除权限,授予权限的对象可以删除该数据节点的子节点。
  5. 数据节点(a:admin)管理者权限,授予权限的对象可以对该数据节点体进行ACL权限设置。

怎么查看和设置某个节点的ACL权限信息呢

通过getAcl来获取某个节点的权限信息,通过setAcl来设置某个节点的权限信息。


5、Zookeeper数据持久化

zookeeper的数据是存储在内存中的吗,怎么进行持久化操作呢?

zookeeper和redis很像,数据都是在内存中的,持久化也是两种方式,一种是记录事务日志,一种是快照方式。