这样学习ZooKeeper离大厂所需技能要求还远吗
概述
定义
Apache ZooKeeper是一种用于构建分布式应用的高性能、高度可靠、开源的分布式协调服务,提供如配置信息维护、命名、分布式同步、组服务等功能,可以实现如分布式共识、组管理、领导选举和到场协议;同时也是Google的Chubby一个Java语言版的开源实现。 最新版本3.7.0
ZooKeeper翻译为中文则为动物园管理员,而众所周知ZooKeeper是大数据生态下的重要组件,是大数据生态的基石之一,而我们也知道大部分大数据生态下组件是以动物命名并作为其Logo,比如Hive、Hbase、Flink等,所以ZooKeeper命名就更加生动贴切。官网客户端API支持语言有Java和C,而我们从事Java技术栈的开发人员更多使用的是Apache Curator,由Netflix公司开源的一套ZooKeeper的客户端框架,为开发人员屏蔽底层细节的开发工作如连接重连、反复注册Watcher和NodeExistsException异常,也封装了一些高级特性如分布式锁、Cache事件监听、选举、分布式Barrier等,可谓是ZooKeeper开发使用的利器。
应用场景
-
命名服务
- 依赖Zookeeper可以生成全局唯一的节点ID,来对分布式系统中的资源进行管理。
-
分布式协调
- 这是Zookeeper的核心使用了,利用Watch的监听机制,一个系统的某个节点状态发生改变,另外系统可以得到通知。
-
集群管理
- 分布式集群中状态的监控和管理,使用Zookeeper来存储。
-
分布式锁
- 利用Zookeeper创建临时顺序节点的特性。
- 保持独占:每个znode都可以看作一把锁,在createZnode的时候,每个客户端都去创建/distribute_lock,最终创建成功的那个客户端就拥有了这把锁,用完之后删除/distribute_lock即可。
- 控制时序:在/distribute_lock下面创建临时顺序节点,编号最小的拥有这把锁,用完删除。
- 利用Zookeeper创建临时顺序节点的特性。
-
注册中心
-
担任服务生产者和服务消费者的注册中心,服务生产者将自己提供的服务注册到Zookeeper中心,服务的消费者在进行服务调用的时候先到Zookeeper中查找服务,获取到服务生产者的详细信息之后,再去调用服务生产者的内容与数据。
-
-
数据发布订阅
- 常见的场景是配置中心,发布者把数据发布到 ZooKeeper 的一个或一系列的节点上,供订阅者进行数据订阅,达到动态获取数据的目的。采用的是推拉结合的方式:
- 推: 服务端会推给注册了监控节点的客户端 Wathcer 事件通知。
- 拉: 客户端获得通知后,然后主动到服务端拉取最新的数据。
- 常见的场景是配置中心,发布者把数据发布到 ZooKeeper 的一个或一系列的节点上,供订阅者进行数据订阅,达到动态获取数据的目的。采用的是推拉结合的方式:
-
分布式队列
- 同步队列:当一个队列的所有成员都聚集时,这个队列才可用;只需要在约定目录下创建一个Watcher监听,当达到指定数量时,就触发Watcher通知机制。
- FIFO队列:与分布式锁差不多,入队时有编号,出队时按编号依次出队。
-
负载均衡、选主等
集群角色
- leader角色
- 事务请求的唯一调度和处理者,保证集群事务处理的顺序性。
- 集群内部各服务的调度者。
- 处理所有的事务请求(写请求),也可以处理读请求,集群中只能有一个Leader,发起投票。
- Follower角色
- 处理客户端的非事务请求,转发事务请求给Leader服务器。
- 参与事务请求Proposal的投票。
- 参与Leader选举投票。
- 只处理读请求,同时作为 Leader的候选节点,即如果Leader宕机,Follower节点要参与到新的Leader选举中,有可能成为新的Leader节点。
- Observer角色
- 处理客户端的非事务请求,转发事务请求给Leader服务器。
- 不参与任何形式的投票选举。
- 只能处理读请求。
集群安装
ZooKeeper官方下载地址 //zookeeper.apache.org/releases.html
我们下载二进制包即可,官方也同时提供源码文件。
#单机版使用比较简单,下载解压、执行启动脚本文件就完成了。zookeeper重要就是分布式和高可靠性,如果自己都是单点那就说不过去了,索引我们这里进行集群部署,准备三台虚拟机,使用xshell批量执行所有窗口的命令,可以提高部署效率,每台虚拟机先安装jdk环境,这个已准备好,然后创建目录下载zookeeper的二进制文件
wget //dlcdn.apache.org/zookeeper/zookeeper-3.7.0/apache-zookeeper-3.7.0-bin.tar.gz
#解压文件
tar -xvf apache-zookeeper-3.7.0-bin.tar.gz
#进入zookeeper根目录
cd apache-zookeeper-3.7.0-bin/
#创建数据目录和日志目录
mkdir data log
#进入配置文件
cd conf/
#重命名配置文件
mv zoo_sample.cfg zoo.cfg
#修改配置文件的内容为如下:
vim zoo.cfg
# 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
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
#存放数据文件
dataDir=/home/commons/apache-zookeeper-3.7.0-bin/data
#存放日志文件
dataLogDir=/home/commons/apache-zookeeper-3.7.0-bin/log
# the port at which the clients will connect
clientPort=2181
#zookeeper cluster,2888为选举端口,3888为心跳端口
server.1=192.168.50.34:2888:3888
server.2=192.168.50.35:2888:3888
server.3=192.168.50.36:2888:3888
#在我们配置的dataDir指定的目录下面,创建一个myid文件,里面内容为一个数字,用来标识当前主机,这个也是zookeeper用来领导选取算法输入参数之一,conf/zoo.cfg文件中配置的server.X中X为什么数字,则myid文件中就输入这个数字:分别在三台上执行各自对应myid。
echo "1" >/home/commons/apache-zookeeper-3.7.0-bin/data/myid
echo "2" >/home/commons/apache-zookeeper-3.7.0-bin/data/myid
echo "3" >/home/commons/apache-zookeeper-3.7.0-bin/data/myid
#进入bin文件夹下执行启动脚本
./zkServer.sh start
#通过jps或者ps查看zookeeper进程情况
ps -ef |grep zookeeper
#查看当前节点的状态,从下面的结果得出36是集群的leader,另外两个节点是follower
./zkServer.sh status
#通过客户端脚本,可以在任何一个结点上建立到集群的连接进而操作整个ZooKeeper集群
./zkCli.sh -server 192.168.50.34:2181
#创建目录
create /itxs "hello zookeeper"
#查看目录,当我们连接到集群其他节点如35或36上再次查看节点的数据也是相同的,也即是zookeeper实现集群内部的数据同步
get /itxs
还可以使用zookeeper-dev-ZooInspector.jar可视化客户端工具,搜索名称下载即可
数据节点
#查看节点详细数据
stat /temp
#节点详细说明
1)czxid-创建节点的事务zxid
每次修改ZooKeeper状态都会收到一个zxid形式的时间戳,也就是ZooKeeper事务ID。
事务ID是ZooKeeper中所有修改总的次序。每个修改都有唯一的zxid,如果zxid1小于zxid2,那么zxid1在zxid2之前发生。
2)ctime - znode被创建的毫秒数(从1970年开始)
3)mzxid - znode最后更新的事务zxid
4)mtime - znode最后修改的毫秒数(从1970年开始)
5)pZxid-znode最后更新的子节点zxid
6)cversion - znode子节点变化号,znode子节点修改次数
7)dataversion - znode数据变化号
8)aclVersion - znode访问控制列表的变化号
9)ephemeralOwner- 如果是临时节点,这个是znode拥有者的session id。如果不是临时节点则是0。
10)dataLength- znode的数据长度
11)numChildren - znode子节点数量
在 Zookeeper 中,可以说 Zookeeper 中的所有存储的数据是由 znode 组成的,节点也称为 znode,并以 key/value 形式存储数据。整体结构类似于 linux 文件系统的模式以树形结构存储。其中根路径以 / 开头。通过get命令可以获取如下信息
节点类型
ZooKeeper支持7种znode类型,千万不要再说只有4种了
- PERSISTENT(持久化目录节点)
- 客户端与zookeeper断开连接后,该节点依旧存在,只要不手动删除该节点,他将永远存在,默认类型。
- PERSISTENT_SEQUENTIAL(持久化顺序目录节点)
- 客户端与zookeeper断开连接后,该节点依旧存在,Zookeeper还会给该节点名称进行顺序编号,单调递增。
- EPHEMERAL(临时目录节点)
- 客户端与zookeeper断开连接后,该节点被删除。
- EPHEMERAL_SEQUENTIAL(临时顺序目录节点)
- 客户端与zookeeper断开连接后,该节点被删除,Zookeeper还会给该节点名称进行顺序编号,单调递增。
- Container (容器节点)
- zookeeper 3.5.3 版本新增的,容器节点主要用来容纳字节点,如果没有给其创建子节点,容器节点表现和持久化节点一样,如果给容器节点创建了子节点,后续又把子节点清空,容器节点也会被zookeeper删除。特殊用途对于诸如leader、lock等非常有用,服务端会定期扫描这些节点,当该节点下面没有子节点时(或其他条件时)服务端会自动删除节点。
- PERSISTENT_WITH_TTL(持久化TTL节点)
- zookeeper的扩展类型,如果znode在给定的TTL内没有被修改,它将在没有子节点时被删除。需要额外配置才能启用,必须在zookeeper的bin/zkService.sh中的启动zookeeper的java环境中设置环境变量zookeeper.extendedTypesEnabled=true(具体做法在下边),基本和容器相同,当超过 TTL 时间节点下面都没有再创建子节点时会被删除,但是当创建子节点会重置该超时时间。
- PERSISTENT_SEQUENTIAL_WITH_TTL(持久化顺序TTL节点)
- 和TTL节点类似,只是多了顺序性,该特性是由父节点维护的一个自增整型数字。
核心功能
ZooKeeper主要提供文件系统、通知机制和集群管理核心功能
-
文件系统
- zookeeper集群是有一个叫做命名节点空间的概念,其中节点就是znode,在zookeeper的文件系统中有两种节点,一是数据节点,二是目录节点,但是只有数据节点能存放数据。
- zookeeper集群为了维护高吞吐和低延迟的特性,就维护了这样树状的目录结构,而且数据节点的存储量不能太大,最多为1M。
-
通知机制
- 当某个client监听某个节点时,当该节点发生变化时(有可能是增加子节点,或者节点值变了等),zk就会通知监听该节点的客户端来处理。
-
集群管理
- zk本身是一个集群结构,有一个leader节点,负责写请求,多个follower负责响应读请求。并且在leader节点故障时,会自动根据选举机制从剩下的follower中选出新的leader。
架构原理
分布式基础理论
ZooKeeper可以说是分布式理论中最典型的中间件教科书,为了更好理解分布式领域技术,我们需要先了解CAP、BASE这两个分布式基础理论,也是高频出现在大厂或名企的面试中特别是大中型的互联网企业。
CAP理论
- 一致性(Consistency):数据在多个副本之间是否能够保持一致的特性。(当一个系统在一致状态下更新后,应保持系统中所有数据仍处于一致的状态)
- 可用性(Availability):系统提供的服务必须一直处于可用状态,对每一个操作的请求必须在有限时间内返回结果。好的可用性主要是指系统能够很好的为用户服务,不出现用户操作失败或者访问超时等用户体验不好的情况
- 分区容错性(Tolerance of network Partition):分布式系统在遇到网络分区故障时,仍然需要保证对外提供一致性和可用性的服务,除非整个网络都发生故障;比如节点1和节点3出现故障,但是依然能够很好地对外提供服务。
- CAP理论是指在一个分布式系统中最多只能同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance)这三项中的两项
- 对于分布式系统来说,P(分区容忍性)是基本要求必须要保证的,否则就失去了价值,所以剩下要么CP组合,要么是AP组合。因此设计分布式数据系统,就是在一致性和可用性之间取一个平衡,对于大多数场景并不需要强一致性,因此牺牲一致性而换取高可用性,这个也是目前多数分布式数据库产品的方向。但这里很多人不要产生了误区,牺牲一致性并不是不要一致性,而是在可用性前提下尽可能提高数据一致性,而数据一致性从强到弱可以分为强一致性、最终一致性、弱一致性。
- 强一致性
- 对于关系型数据库,要求更新过的数据能被后续的访问都能看到,这是强一致性。比如小林更新values0到values1,那幺小李读取值时也应该是values1。
- 弱一致性
- 如果能容忍后续的部分或者全部访问不到,则是弱一致性。比如小林更新values0到values1,可以容忍那幺小李读取值时是values0。
- 最终一致性
- 如果经过一段时间后要求能访问到更新后的数据,则是最终一致性。比如小林更新values0到values1,可以使得小李在一段时间之后读取值时是values1。
- 强一致性
BASE理论
- BASE包含 Basically Available(基本可用)、Soft state(软状态)和 Eventually consistent (最终一致性)这三个短语的缩写。
[外链图片转存中…(img-ppG13Ys0-1640099320347)]
-
BASE理论是是eBay 的架构师 Dan Pritchett 提出,对CAP中AP的一个扩展,通过牺牲强一致性来获得可用性,当出现故障允许部分不可用但要保证核心功能可用,允许数据在一段时间内是不一致的,但最终达到一致状态。满足BASE理论的事务,我们称之为“柔性事务”。
- Basically Available 基本可用:分布式系统在出现故障时,允许损失部分可用功能,保证核心功能可用。可以体现在时间上的损失和功能上的损失。如部分用户双十一淘宝页面卡顿或降级处理。
- Soft state 软状态:由于不要求强一致性,所以BASE允许系统中存在中间状态(也叫软状态),即系统的不同节点的数据副本之间的数据同步过程存在延迟,这个状态不影响系统可用性,如订单的”支付中”、“数据同步中”等状态,待数据最终一致后状态改为“成功”状态。
Zab协议
zookeeper非常核心就是原子广播保证各个server之间的同步,而实现这个机制就是Zab协议(全称 Zookeeper Atomic Broadcast),Zab协议是为分布式协调服务Zookeeper专门设计的一种支持崩溃恢复的原子广播协议;ZAB协议包括两种基本的模式:崩溃恢复和消息广播:
- 当整个zookeeper集群刚刚启动或者Leader服务器宕机、重启或者网络故障导致不存在过半的服务器与Leader服务器保持正常通信时,所有进程(服务器)进入崩溃恢复模式,首先选举产生新的Leader服务器,然后集群中Follower服务器开始与新的Leader服务器进行数据同步。
- 当集群中超过半数机器与该Leader服务器完成数据同步之后,退出恢复模式进入消息广播模式,Leader服务器开始接收客户端的事务请求生成事物提案来进行事务请求处理。
Zab 协议的原理可细分为四个阶段:选举(Leader Election)、发现(Discovery)、同步(Synchronization)和广播(Broadcast)
- Leader election(选举阶段)
- 节点在一开始都处于选举阶段,只要有一个节点得到超过半数节点的票数,它就可以当选准 Leader。
- Discovery(发现阶段)
- 在这个阶段,Followers跟准Leader进行通信,同步Followers最近接收的事务提议。
- Synchronization(同步阶段)
- 同步阶段主要是利用Leader前一阶段获得的最新提议历史,同步集群中所有的副本。同步完成之后准Leader才会成为真正的Leader。
- Broadcast(广播阶段)
- 到了这个阶段,Zookeeper集群才能正式对外提供事务服务,并且Leader 可以进行消息广播。同时如果有新的节点加入,还需要对新节点进行同步。
分布式一致性算法和共识机制?
Paxos 分布式一致性算法,强一致算法,也是一种分布式共识算法,基于提案及核心理念也都是基于多数派原则,大部分也是基于2pc两阶段提交(投票-执行)、3pc三阶段提(交投票-预提交-执行)的演变,上面说的Zab与Paxos 具有一些相似之处,而从设计上看ZAB协议和 Raft本质 更是比较类似。Paxos 协议有三大分支包括basic、multi、fast,都是比较难以理解,而Raft协议则是Paxos简化版或者变种版,很多开源中间件如Nacos、Etcd、Redis哨兵集群、Consul、Tidb都有Raft协议的实现。Raft原理中主要涉及两大活动选主和日志复制:
- Raft中有三个角色leader follower candidate,所有节点默认为跟随者,follower可以成为候选者,发起投票,过半就成为leader,之后领导者就开始向其关注者发送条目信息,这些消息是以心跳超时指定间隔发送,然后关注者回复每个附加条目信息,所有更改都通过leader。
- Raft选举超时follower等待成为candidate的超时时间,Term任期编号自增。超时时钟做随机,新的leader同步所有数据信息包括任期,每个节点有一个倒计时器(election timeout),时间随机在150~300ms,当收到选举请求和leader的心跳重置,发送term编号,每个编号跟随者发送一次不再回复发送,也即是每个任期只投票一次,重票则重新进行新任期选举;网络分区后,任期较低的一边同步任期高的数据。
Watch机制
客户端注册监听他关心的目录节点,当目录节点发生变化(数据改变、被删除、子目录节点增加删除)时,Zookeeper会通知客户端。client端会对某个znode建立一个watcher事件,当该znode发生变化时,zk会主动通知watch这个znode的client,然后client根据znode的变化来做出业务上的改变等。首先客户端会向服务端注册一个Watcher监听,当服务端的某些指令触发了这个Watcher的话,服务端就会向客户端返回一个消息通知,客户端接收到消息之后便可以做出业务上的改变,主要流程如下:
- 客户端注册Watcher:客户端先向Zookeeper服务端成功注册想要监听的节点状态。
- 首先会访问getData()/getChildren()/exist()三个API,传入Watcher对象。
- 标记请求request,将Watcher封装成WatcherRegistration对象。
- 再封装成Packet对象,服务端发送request。
- 接收到服务端的request请求之后,将Watcher注册到zkWatcherManager中进行管理。
- 将结果返回给客户端,注册成功。
- 服务端触发Watcher:同时客户端本地会存储该监听器相关的信息在WatchManager中。
- 首先根据客户端的请求判断是否需要注册Watcher。
- 比如服务端触发了setData()/delete()/create()方法,会触发一个叫做NodeDataChanged()的事件。
- 服务端会将触发的事件类型、节点的路径封装成一个叫做WatchedEvent的对象。
- 再向zkWatcherManager中的WatcherTable中根据节点路径查找。若找不到,说明客户端没有注册过Watche,若找到,将Watcher从WatcherTable中删除(说明Watcher监听是一次性的)。
- 调用process方法触发Watcher,主要是通过Servercnxn的TCP连接来通知客户端。
- 客户端回调Watcher:当Zookeeper服务端监听的数据状态发生变化时,Zookeeper就会主动通知发送相应事件信息给相关会话客户端,从WatherManager中取出对应Wather对象执行回调逻辑。
- 客户端有个SendThread来接收Watcher通知的线程,接收的通知之后会交由EventThread线程处理。
- 客户端的Watcher监听也是一次性的,一旦触发也会被删除。
ZookeeperServer工作状态
Zookeeper服务器具有四种状态,分别是LOOKING、FOLLOWING、LEADING、OBSERVING。
- LOOKING:寻找Leader状态。当服务器处于该状态时,它会认为当前集群中没有Leader,因此需要进入Leader选举状态。
- FOLLOWING:跟随者状态。表明当前服务器角色是Follower。
- LEADING:领导者状态。表明当前服务器角色是Leader。
- OBSERVING:观察者状态。表明当前服务器角色是Observer。
ZooKeeper是如何保证事务的顺序一致性的?
- zookeeper采用全局递增的事务id(zxid)来保证事务的顺序一致性的。
- 所有的提议在被提出的都会携带这个zxid,zxid是一个64位的数字;高32位是个epoch(时期,纪元,世,新时代)值,表示leader选举周期,每进行一次leader选举,该数字就会+1;后32位用来表示递增计数,当产生新的提议时,会依据数据库的两阶段提交过程,首先会像其它节点发送执行请求,如果超过半数以上的机器正确执行,那么该事务就可以被执行。
Zookeeper的架构与集群规则?
一个领导者和多个跟随者,超过半数过半机制,每个节点有一份全量数据,更新请求转发且按顺序依次执行,数据更新原子性原则,实时性(客户端可以读取最新数据,有序性是zookeeper中非常重要的一个特性,所有的更新都是全局有序的,每个更新都有一个唯一的zxid,而读请求只会相对于更新有序,也就是读请求的返回结果中会带有这个zookeeper最新的zxid;Zookeeper是可以集群复制的,集群间通过Zab协议(Zookeeper Atomic Broadcast)来保持数据的一致性。
集群机器台数规则为2N+1台,N>0,也即是集群数量建议为基数台,最小集群为3台,最低生产环境一般建议三个机房,每个机房分别为3、2、2。由于设计和实现Zookeeper集群也不会出现脑裂问题(当出现网络分区割断后分布式现象问题)。
- 首先我们知道zookeeper选举的规则可用节点数量 > 总节点数量/2,集群中只要有过半的机器是正常工作的,那么整个集群对外就是可用的。
- 比如标记一个写是否成功是要在超过一半节点发送写请求成功时才认为有效。同样,Zookeeper选择领导者节点也是在超过一半节点同意时才有效。最后,Zookeeper是否正常是要根据是否超过一半的节点正常才算正常。
- 2n和2n-1的容忍度是一样的,都是n-1,所以不需要增加一个不必要的zookeeper节点。
- zookeeper的选举策略也是需要半数以上的节点同意才能当选leader,如果是偶数节点可能导致票数相同的情况。
怎么做leader选举?
当Zookeeper集群在启动时,或者当leader节点出现网络中断、崩溃等情况时,Zookeeper就会进入恢复模式并选举产生新的 Leader。
- SID: ServerID,用来唯一标识一台Zookeeper集群中的机器,全局唯一,serverid也即是myid,在配置文件中指定。
- ZXID:事务ID,用来唯一标识一次服务器状态的变更,在同一时刻中集群内部每一台机器的ZXID未必完全一致。
大体过程:Leader收到消息请求先生成全局自增zxid,然后为每个follower创建FIFO队列保证有序,将消息作为提案发给所有follower, follower收到提案先写磁盘然后回复ack给leader,当leader收到半数以上follower的ack后向follower发送commit请求,同时本地执行存储和业务响应结果,follower收到后commit提交更新内存,执行投票不需要观察者的ack但观察者必须同步leader数据。
- 第一步:每个Server发出一个投票提议,并且先投自己。
- 第二步:接收来自各个服务器的投票,节点进行投票。
- 第三步:PK选票并更新选票(pk进行改票,集合zxid,serverid根据数据最近原则),存内存、磁盘。
- 第四步:统计所有投票,判断是否有过半机器接收到相同的投票信息;核心是集合2pc两阶段提交和过半机制,并通过原子广播保证数据同步。
- 第五步:改变服务器状态,选主完成并且有一半节点和leadder数据同步完成退出恢复模式,一旦确定Leader,每个服务器更新自己的状态。
Zookeeper写数据流程
- Client向Zookeeper的Server1上写数据,发送一个写请求。
- 如果Server1不是Leader,那么Server1会把接收到的请求进一步转发给Leader,因为每个Zookeeper集群里面有一个是Leader。
- Leader会将写请求广播给各个Server,各个Server写成功后会通知Leader。
- 当Leader收到大多数Server数据写成功了,就说明数据写成功了.如果这里有五个节点的话,只要有三个节点数据写成功了.那么就认为数据写成功了。
- 写成功以后,Leader就会告诉Server1数据写成功了。
- Server1会进一步通知Client数据写成功了,这时就认为整个写操作成功。
zookeeper数据同步实现方式
zookeeper实现数据同步有4种方式,即直接差异化同步、先回滚再差异化同步、仅回滚同步、全量同步;首先先从learner(follower和observer节点的统称)节点获取最后一次操作数据的zxid,再从leader节点中获取最小的minZxid和最大的maxZxid。
- 如果minZxid<zxid<maxZxid –>采用直接差异化同步
- 如果leader服务器发现learner服务器包含了自己不存在的数据,那么learner服务器需要回滚到leader包含的数据然后在差异化处理 –>先回滚再差异化同步
- 如果zxid>maxZxid –>仅回滚同步即可
- 如果zxid<minZxid –>全量同步
权限控制列表ACL
zookeeper的权限控制列表包含三个部分
- 授权模式
- IP:授权模式精确到IP粒度。
- Digest:相当于username:password,最常用的一种授权模式。
- World:相当于最特殊的Digest模式world:everyone,最开放的一种授权模式。
- Super:超级用户。
- 授权对象:被授予权限的用户例如某个IP
- 权限
- Create:创建。
- Delete:删除。
- Read:读。
- Write:写。
- Admin:管理