Zookeeper
它作为Hadoop
项目中的一个开源子项目,是一个经典的分布式数据一致性解决方案,致力于为分布式应用提供一个高性能、高可用,且具有严格顺序访问控制能力的分布式协调服务。
zookeeper
维护了一个类似文件系统的数据结构,每个子目录(/微信、/微信/公众号)都被称作为 znode
即节点。和文件系统一样,我们可以很轻松的对 znode
节点进行增加、删除等操作,而且还可以在一个znode
下增加、删除子znode
,区别在于文件系统的是,znode
可以存储数据(严格说是必须存放数据,默认是个空字符)。
由于zookeeper
是目录节点结构,在获取和创建节点时,必须要以“/”
开头,否则在获取节点时会报错 Path must start with / character
。
[zk: localhost:2181(CONNECTED) 13] get test
Command failed: java.lang.IllegalArgumentException: Path must start with / character
根节点名必须为“/XXX”
,创建子节点时必须要带上根节点目录“/XXX/CCC”
、“/XXX/AAA”
。
例如:想要获取下图 程序员内点事
节点必须拼接完整的路径 get /微信/公众号/程序员内点事
get /微信/公众号/程序员内点事
在这里插入图片描述
znode
被用来存储 byte级
或 kb级
的数据,可存储的最大数据量是1MB
(请注意:一个节点的数据量不仅包含它自身存储数据,它的所有子节点的名字也要折算成Byte数计入,因此znode
的子节点数也不是无限的)虽然可以手动的修改节点存储量大小,但一般情况下并不推荐这样做。
一个znode
节点不仅可以存储数据,还有一些其他特别的属性。接下来我们创建一个/test
节点分析一下它各个属性的含义。
[zk: localhost:2181(CONNECTED) 6] get /test
456
cZxid = 0x59ac //
ctime = Mon Mar 30 15:20:08 CST 2020
mZxid = 0x59ad
mtime = Mon Mar 30 15:22:25 CST 2020
pZxid = 0x59ac
cversion = 0
dataVersion = 2
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 3
numChildren = 0
节点属性 | 注解 |
---|---|
cZxid | 该数据节点被创建时的事务Id |
mZxid | 该数据节点被修改时最新的事物Id |
pZxid | 当前节点的父级节点事务Id |
ctime | 该数据节点创建时间 |
mtime | 该数据节点最后修改时间 |
dataVersion | 当前节点版本号(每修改一次值+1递增) |
cversion | 子节点版本号(子节点修改次数,每修改一次值+1递增 |
aclVersion | 当前节点acl版本号(节点被修改acl权限,每修改一次值+1递 |
ephemeralOwner | 临时节点标示,当前节点如果是临时节点,则存储的创建者的会话id(sessionId),如果不是,那么值=0 |
dataLength | h 当前节点所存储的数据长度 |
numChildren | ren 当前节点下子节点的个数 |
我们看到一个znode
节点的属性比较多,但比较主要的属性还是zxid
、version
、acl
这三个。
Zxid:
znode
节点状态改变会导致该节点收到一个zxid
格式的时间戳,这个时间戳是全局有序的,znode节点的建立或者更新都会产生一个新的。如果zxid1
的值 < zxid2
的值,那么说明zxid2
发生的改变在zxid1
之后。每个znode节点都有3个zxid
属性,cZxid
(节点创建时间)、mZxid
(该节点修改时间,与子节点无关)、pZxid
(该节点或者该节点的子节点的最后一次创建或者修改时间,孙子节点无关)。
zxid
属性主要应用于zookeeper
的集群,这个后边介绍集群时详细说。
Version:
znode
属性中一共有三个版本号dataversion
(数据版本号)、cversion
(子节点版本号)、aclversion
(节点所拥有的ACL权限版本号)。
znode
中的数据可以有多个版本,如果某一个节点下存有多个数据版本,那么查询这个节点数据就需要带上版本号。每当我们对znode
节点数据修改后,该节点的dataversion
版本号会递增。当客户端请求该znode
节点时,会同时返回节点数据和版本号。另外当dataversion
为 -1
的时候可以忽略版本进行操作。对一个节点设置权限时aclVersion
版本号会递增,下边会详细说ACL权限控制。
验证一下,我们修改/test
节点的数据看看dataVersion
有什么变化,发现dataVersion
属性变成了 3,版本号递增了。
[zk: localhost:2181(CONNECTED) 10] set /test 8888
cZxid = 0x59ac
ctime = Mon Mar 30 15:20:08 CST 2020
mZxid = 0x59b6
mtime = Mon Mar 30 16:58:08 CST 2020
pZxid = 0x59ac
cversion = 0
dataVersion = 3
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 4
numChildren = 0
zookeeper
有四种类型的znode
,在用客户端 client
创建节点的时候需要指定类型。
zookeeper.create("/公众号/程序员内点事", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
PERSISTENT
-持久化目录节点 :client创建节点后,与zookeeper断开连接该节点将被持久化,当client再次连接后节点依旧存在。PERSISTENT_SEQUENTIAL
-持久化顺序节点 :client创建节点后,与zookeeper断开连接该节点将被持久化,再次连接节点还存在,zookeeper会给该节点名称进行顺序编号,例如:/lock/0000000001、/lock/0000000002、/lock/0000000003。EPHEMERAL
-临时目录节点 :client与zookeeper断开连接后,该节点即会被删除EPHEMERAL_SEQUENTIAL
-临时顺序节点 :client与zookeeper断开连接后,该节点被删除,会给该节点名称进行顺序编号,例如:/lock/0000000001、/lock/0000000002、/lock/0000000003。ACL
:即 Access Control List
(节点的权限控制),通过ACL
机制来解决znode
节点的访问权限问题,要注意的是zookeeper
对权限的控制是基于znode
级别的,也就说节点之间的权限不具有继承性,即子节点不继承父节点的权限。
zookeeper
中设置ACL权限的格式由<schema>:<id>:<acl>
三段组成。
schema :表示授权的方式
world
:表示任何人都可以访问auth
:只有认证的用户可以访问digest
:使用username :password用户密码生成MD5哈希值作为认证IDhost/ip
:使用客户端主机IP地址来进行认证id:权限的作用域,用来标识身份,依赖于schema选择哪种方式。
acl:给一个节点赋予哪些权限,节点的权限有create,、delete、write、read、admin 统称 cdwra
。
world
:表示任何人都可以访问我们用 getAcl
命令来看一下,没有设置过权限的znode
节点,默认情况下的权限情况。
[zk: localhost:2181(CONNECTED) 12] getAcl /test
'world,'anyone
: cdrwa
看到没有设置ACL属性的节点,默认schema 使用的是world
,作用域是anyone
,节点权限是cdwra
,也就是说任何人都可以访问。
那我们如果要给一个schema 为非world
的节点设置world
权限咋搞?
setAcl /test world:anyone:crdwa
auth
:只有认证的用户可以访问schema 用auth
授权表示只有认证后的用户才可以访问,那么首先就需要添加认证用户,添加完以后需要对认证的用户设置ACL权限。
addauth digest test:password(明文)
需要注意的是设置认证用户时的密码是明文的。
[zk: localhost:2181(CONNECTED) 2] addauth digest user:user //用户名:密码
[zk: localhost:2181(CONNECTED) 5] setAcl /test auth:user:crdwa
[zk: localhost:2181(CONNECTED) 6] getAcl /test
'digest,'user:ben+k/3JomjGj4mfd4fYsfM6p0A=
: cdrwa
实际上我们这样设置以后,就是将这个节点开放给所有认证的用户,setAcl /test auth:user:crdwa
相当于setAcl /test auth::crdwa
。
digest
:用户名:密码的验证方式用户名:密码方式授权是针对单个特定用户,这种方式是不需要先添加认证用户的。
如果在代码中使用zookeeper客户端设置ACL,那么密码是明文的,但若是zk.cli等客户端操作就需要将密码进行sha1
及base64
处理。
setAcl <path> digest:<user>:<password(密文)>:<acl>
setAcl /test digest:user:jalRr+knv/6L2uXdenC93dEDNuE=:crdwa
那么密码如何加密嘞?有以下几种方式:
通过shell
命令加密
echo -n <user>:<password> | openssl dgst -binary -sha1 | openssl base64
使用zookeeper
自带的类库org.apache.zookeeper.server.auth.DigestAuthenticationProvider
生成
java -cp /zookeeper-3.4.13/zookeeper-3.4.13.jar:/zookeeper-3.4.13/lib/slf4j-api-1.7.25.jar \
org.apache.zookeeper.server.auth.DigestAuthenticationProvider \
root:root
root:root->root:qiTlqPLK7XM2ht3HMn02qRpkKIE=
host/ip
:使用客户端主机IP地址来进行认证这种方式就比较好理解了,通过对特定的IP地址,也可以是一个IP段进行授权。
[zk: localhost:2181(CONNECTED) 3] setAcl /test0000000014 ip:127.0.0.1:crdwa
cZxid = 0x59ac
ctime = Mon Mar 30 15:20:08 CST 2020
mZxid = 0x59b6
mtime = Mon Mar 30 16:58:08 CST 2020
pZxid = 0x59ac
cversion = 0
dataVersion = 3
aclVersion = 3 // 这个版本一直在增加
ephemeralOwner = 0x0
dataLength = 4
numChildren = 0
我们在开头就说过:zookeeper
可以为dubbo
提供服务的注册与发现,作为注册中心,但你有想过zookeeper
为啥能够实现服务的注册与发现吗?这就不得不说一下zookeeper
的灵魂 Watcher
(监听者)。
watcher
是zooKeeper
中一个非常核心功能 ,客户端watcher
可以监控节点的数据变化以及它子节点的变化,一旦这些状态发生变化,zooKeeper服务端就会通知所有在这个节点上设置过watcher
的客户端 ,从而每个客户端都很快感知,它所监听的节点状态发生变化,而做出对应的逻辑处理。
简单的介绍了一下watcher
,那么我们来分析一下,zookeeper
是如何实现服务的注册与发现。zookeeper
的服务注册与发现,主要应用的是zookeeper
的znode
节点数据模型和watcher
机制,大致的流程如下:
在这里插入图片描述
Provider
)启动时,会向zookeeper服务端
注册服务信息,也就是创建一个节点,例如:用户注册服务com.xxx.user.register
,并在节点上存储服务的相关数据(如服务提供者的ip地址、端口等)。Consumer
)启动时,根据自身配置的依赖服务信息,向zookeeper服务端
获取注册的服务信息并设置watch监听
,获取到注册的服务信息之后,将服务提供者的信息缓存在本地,并进行服务的调用。zookeeper
服务端断开连接,zookeeper
服务端上服务提供者对应服务节点会被删除(例如:用户注册服务com.xxx.user.register
),随后zookeeper
服务端会异步向所有消费用户注册服务com.xxx.user.register
,且设置了watch监听
的服务消费者发出节点被删除的通知,消费者根据收到的通知拉取最新服务列表,更新本地缓存的服务列表。上边的过程就是zookeeper
可以实现服务注册与发现的大致原理。
znode
节点可以设置两类watch
,一种是DataWatches
,基于znode节点的数据变更从而触发 watch
事件,触发条件getData()
、exists()
、setData()
、 create()
。
另一种是Child Watches
,基于znode的孩子节点发生变更触发的watch事件,触发条件 getChildren()
、 create()
。
而在调用 delete()
方法删除znode时,则会同时触发Data Watches
和Child Watches
,如果被删除的节点还有父节点,则父节点会触发一个Child Watches
。
watch
对节点的监听事件是一次性的!客户端在指定的节点设置了监听watch
,一旦该节点数据发生变更通知一次客户端后,客户端对该节点的监听事件就失效了。
如果还要继续监听这个节点,就需要我们在客户端的监听回调中,再次对节点的监听watch
事件设置为True
。否则客户端只能接收到一次该节点的变更通知。
服务的注册与发现功能只是zookeeper的冰山一角,它还能实现诸如分布式锁、队列、配置中心等一系列功能,接下来我们只分析一下原理,具体的实现大家上网查一下资料还是比较全的。
zookeeper
基于watcher
机制和znode
的有序节点,天生就是一个分布式锁的坯子。首先创建一个/test/lock
父节点作为一把锁,尽量是持久节点(PERSISTENT类型),每个尝试获取这把锁的客户端,在/test/lock
父节点下创建临时顺序子节点。
由于序号的递增性,我们规定序号最小的节点即获得锁。例如:客户端来获取锁,在/test/lock
节点下创建节点为/test/lock/seq-00000001
,它是最小的所以它优先拿到了锁,其它节点等待通知再次获取锁。/test/lock/seq-00000001
执行完自己的逻辑后删除节点释放锁。
那么节点/test/lock/seq-00000002
想要获取锁等谁的通知呢?
这里我们让/test/lock/seq-00000002
节点监听/test/lock/seq-00000001
节点,一旦/test/lock/seq-00000001
节点删除,则通知/test/lock/seq-00000002
节点,让它再次判断自己是不是最小的节点,是则拿到锁,不是继续等通知。
以此类推/test/lock/seq-00000003
节点监听/test/lock/seq-00000002
节点,总是让后一个节点监听前一个节点,不用让所有节点都监听最小的节点,避免设置不必要的监听,以免造成大量无效的通知,形成“羊群效应”。
zookeeper
分布式锁和redis
分布式锁相比,因为大量的创建、删除节点性能上比较差,并不是很推荐。
zookeeper实现分布式队列也很简单,应用znode的有序节点天然的“先进先出”,后创建的节点总是最大的,出队总是拿序号最小的节点即可。
现在有很多开源项目都在使用Zookeeper来维护配置,像消息队列Kafka中,就使用Zookeeper来维护broker的信息;dubbo中管理服务的配置信息。原理也是基于watcher
机制,例如:创建一个/config
节点存放一些配置,客户端监听这个节点,一点修改/config
节点的配置信息,通知各个客户端数据变更重新拉取配置信息。
zookeeper
的命名服务:也就是我们常说的服务注册与发现,主要是根据指定名字来获取资源或服务的地址,服务提供者等信息,利用其znode
节点的特点和watcher
机制,将其作为动态注册和获取服务信息的配置中心,统一管理服务名称和其对应的服务器列表信息,我们能够近乎实时地感知到后端服务器的状态(上线、下线、宕机)。
本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/wgQCS4e_wm0JDo813f317w
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。