一同养成写作习惯!这是我参与「日新方案 4 月更文挑战」的第2天,点击检查活动详情。
一、zookeeper的存储结构
zookeeper的存储结构极端类似于文件体系,都是树形结构,如下图所示。
与文件体系不同的是,文件体系分为目录和文件,目录是没有数据的。而zookeeper则悉数称为节点(znode),每个节点既能保存数据又有孩子节点。
zookeeper的根节点都是“/”。
每一个节点(znode)的命名空间(类似于java中的包名)都由其途径组成。zookeeper称上面这种结构为分层命名空间(Hierarchical Namespace)。
例如,根节点的命名空间为“/”,第二层左节点的命名空间为”/app1″,右节点的命名空间为“/app2”。
节点的命名空间咱们又能够了解为是每个节点的标识符,程序能够依据称号定位到具体是哪个节点。
二、什么是znode
上图中的每个节点在zookeeper中称为znode。在zookeeper推荐在znode中存储的数据不超越1M,这是从功能和功率的角度动身。zookeeper作为协调分布式运用的服务中心,一般是存储状况信息、装备信息和本地数据等等。从设计的初衷上看也不是为了存储大量数据预备的。假如真的要存储大数据,应该把数据存储在别的当地比方数据库上,然后在znode上存储他们的引证。
znode在每次更新数据时,都是全量更新,直接覆盖以前的值,不存在追加或许修正其间某个当地的操作。读取数据也是悉数读取。一起,znode的读取和写入都是原子操作。
znode还存储了znode版别信息有三个版别号dataversion(数据版别号)、cversion(子节点版别号)、aclversion(节点所拥有的ACL版别号)。每个版别号其实是一个数字,每次修正对应的版别号就会增加。
比方咱们创立一个节点,create /zk “test”后,在linux下用get /zk后回来的信息如下:
test #znode的数据
cZxid = 0x1e #znode的创立事务id
ctime = Tue Sep 29 06:45:54 CST 2020 #znode的创立时间
mZxid = 0x1e #znode的修正事务id
mtime = Tue Sep 29 06:45:54 CST 2020 #修正时间
pZxid = 0x1e #该节点的子节点列表最后一次修正的版别号,增加子节点或删去子节点就会影响子节点列表,但是修正子节点的数据内容则不影响该值,孙子节点的操作也不影响
cversion = 0 #children节点的版别号,每次子节点修正加1,下同
dataVersion = 0 #数据版别号
aclVersion = 0 #ACL(权限操控列表)版别号
ephemeralOwner = 0x0 #假如节点为暂时节点,那么它的值为这个节点拥有者的session ID;假如该节点不是ephemeral节点, ephemeralOwner值为0.
dataLength = 4 #数据长度
numChildren = 0 #孩子节点的数量
版别号的作用
Zookeeper里边的版别号和咱们了解的版别号不同,它表明的是对数据节点的内容、子节点列表或许ACL信息的修正次数。节点创立时dataversion、aclversion,cversion都为0,每次修正呼应内容其对应的版别号加1。
这个版别号的用途就和分布式场景的一个锁概念有关。比方演出售票中的一个座位,显然每个场次中的每个座位都只要一个,不可能卖出2次。假如A下单的时分显现可售,他想买,那么为了确保他能够下单成功,此刻他人就不能买。这时分就需求有一种机制来确保同一时间只能有一个人去修正该座位的库存。这就用到了锁。锁有失望锁和达观锁。
- 失望锁:它会假定一切不同事务的处理一定会呈现搅扰,数据库中最严格的并发操控战略,假如一个事务A正在对数据处理,那么在整个事务过程中,其他事务都无法对这个数据进行更新操作,直到A事务释放了这个锁。
- 达观锁:它假定一切不同事务的处理不一定会呈现搅扰,所以在大部分操作里不许加锁,但是既然是并发就有呈现搅扰的可能,怎么解决冲突便是一个问题。在达观锁中当你在提交更新恳求之前,你要先去检查你读取这个数据之后该数据是否发生了变化,假如有那么你此次的提交就要抛弃,假如没有就能够提交。
Zookeeper中的版别号便是达观锁,你修正节点数据之前会读取这个数据并记录该数据版别号,当你需求更新时会携带这个版别号去提交,假如你此刻携带的版别号(便是你前次读取出来的)和当时节点的版别号相同则阐明该数据没有被修正过,那么你的提交就会成功,假如提交失败阐明该数据在你读取之后和提交之前这段时间内被修正了。
三、znode节点的四种类型
zookeeper有四种节点,暂时节点,暂时次序节点,耐久节点和耐久次序节点。
3.1 暂时节点
当zookeeper的客户端恳求zookeeper服务端创立暂时节点时,节点的ephemeralOwner为此客户端与服务端的sessionId。当客户端与服务端断开衔接时,暂时节点也会被删去。
3.2 暂时次序节点
当创立的是暂时次序节点时,会在节点称号后面增加序号,不断递加。
举个例子。比方恳求创立的是/zk暂时次序节点,假如此刻服务端没有/zk的节点,那么就会创立/zk-1节点。这时第二个恳求过来了,也是创立暂时次序节点/zk,那么服务端就会创立/zk-2,依次是/zk-3,/zk-4……不断递加下去,一向到2^32。与暂时节点相同的是,当客户端断开链接时,暂时次序节点也会被删去。
3.3 耐久节点
顾名思义,便是创立后除非自动删去,否则会一向存在的节点。
3.4 耐久次序节点
当创立的是耐久次序节点时,举个例子。比方恳求创立的是/zk暂时次序节点,假如此刻服务端没有/zk的节点,那么就会创立/zk-1节点。这是有第二个恳求过来了,也是创立暂时次序节点/zk,那么服务端就会创立/zk-2,不断递加下去,一向到2^32。与耐久节点相同的是,创立后除非自动删去,否则会一向存在。
四、权限操控ACL(Access Control List)
ZooKeeper的权限操控是基于每个znode节点的,需求对每个节点设置权限。
zookeeper每个节点的权限类型有五种:create、read、delete、write、admin
CREATE:创立子节点的权限
READ:读节点数据的权限包含获取它的子节点列表的权限
DELETE:有删去子节点的权限
WRITE:写节点数据的权限
ADMIN:能够设置节点访问操控列表权限
zookeeper的授权战略(Scheme)有5种:world、auth、digest、ip、x509(有一些博客写了Super即超级管理员形式这个类型,可能是老版别,从3.4开始,官方文档介绍ACL的时分就没看到super了)
world:默认方式,悉数都能访问,
auth:认证用户能够运用,(cli中能够经过addauth digest user:pwd 来增加当时上下文中的授权用户)
digest:即用户名:密码这种方式认证,这也是事务体系中最常用的。用username:password字符串来产生一个MD5串,然后该串被用来作为ACL ID。认证是经过明文发送username:password来进行的,当用在ACL时,表达式为username:base64,base64是password的SHA1摘要的编码。
ip:运用客户端的主机IP作为ACL ID 。这个ACL表达式的格局为addr/bits,此刻addr中的有用位与客户端addr中的有用位进行比对。
****x509:uses the client X500 Principal as an ACL ID identity. The ACL expression is the exact X500 Principal name of a client. When using the secure port, clients are automatically authenticated and their auth info for the x509 scheme is set.
ACL 权限操控,运用:scheme:id:perm来标识,主要包括 3 个方面:权限形式(Scheme):授权的战略 授权对象(ID):授权的对象 权限类型(Permission):颁发的权限。权限形式和权限类型便是上文所讲,授权对象(ID)很好了解,便是权限赋予的用户或许一个实体,例如:IP 地址或许机器。
五、事情监听watcher
zookeeper能够向节点注册一个watcher,用来监听节点的变化。当节点状况发生变化时,比方说被删去或许修正,那么它就会发送告诉到监听这个节点的客户端,客户端因此而做出自己的操作。
每个注册仅运用一次,也便是当发生一次节点改动,告诉完客户端之后,假如你需求这个节点下次发生改动时也发送告诉到这个客户端,那么就需求再注册一次监听。