背景
我们项目是集群部署的,通过DUBBO注册到Zookeeper上。
对于一些配置值,会在项目启动后会从数据库查询并加载到各主机缓存中。现在存在这样的问题,当A主机修改了该配置值并更新对应缓存后,如何同步修改到其他主机?我们的解决方案是利用Zookeeper的统一配置管理功能来实现。
Zookeeper介绍
Zookeeper是一个开源的分布式的,为分布式框架提供协调服务的Apache项目
工作机制
Zookeeper从设计模式角度来理解:是一个基于观察者模式设计的分布式服务管理框架——它负责存储和管理大家都关心的数据,然后接受观察者的注册,一旦这些数据的状态发生变化,Zookeeper就将负责通知已经在Zookeeper上注册的那些观察者做出相应的反应。
特点
- Zookeeper:一个领导者(Leader),多个跟谁者(Follower)组成的集群
- 集群中只要有半数以上节点存活,Zookeeper集群就能正常服务,所以Zookeeper适合安装奇数台服务器。
- 全局数据一致:每个Server保存相同的数据副本,Client无论连接到哪个Server,数据都是一致的。
- 更新请求顺序执行,来自同一个Client的更新请求按其发送顺序依次执行。
- 数据更新原子性,一次数据更新要么成功,要么失败。
- 实时性,在一定时间范围内,Client能读到更新数据。
数据模型
Zookeeper数据模型的结构与Unix文件系统很类似,整体上可以看作是一棵树,每个节点称做一个ZNode。
每一个ZNode默认能够存储1MB的数据,每个ZNode都可以通过其路径唯一标识。
节点分类
1)临时节点(EPHEMERAL) :session链接断开就没了;不能创建子节点;不能同名
2)临时顺序节点(EPHEMERAL_SEQUENTIAL) :session链接断开就没了;不能创建子节点;同名节点会在后面添加上序号(分布式锁使用的好处)
3)持久节点(PERSISTENT):session断联、服务端重启还在;可以创建子节点,子节点可以临时也可以持久;不能同名
4)持久顺序节点(PERSISTENT_SEQUENTIAL):session断联、服务端重启还在;可以创建子节点,子节点可以临时也可以持久;同名节点会在后面添加上序号
应用场景
统一命名服务,统一配置管理,统一集群管理,服务器节点动态上下线,软负载均衡等
统一命名服务
在分布式环境下,经常需要对应用/服务进行统一命名,便于识别。
统一配置管理
1)分布式环境下,配置文件同步非常常见。
(1)一般要求一个集群中,所有节点的配置信息是一致的,比如Kafka集群。
(2)对配置文件修改后,希望能够快速同步到各个节点上。
2)配置管理可交由Zookeeper实现。
(1)可将配置信息写入Zookeeper上的一个Znode。
(2)各个客户端服务器监听这个ZNode。
(3)一旦Znode中的数据被修改,Zookeeper将通知各个客户端服务器。
服务器动态上下线
软负载均衡
ZK在缓存一致中的应用思路
为了解决前面提到了集群部署下缓存更新不一致的问题,我们利用Zookeeper的统一配置管理特性,来实现缓存更新一致。
配置项缓存第一次加载时,先注册一个永久节点(ZkClient.createPersistent),再注册一个监听(ZkClient.subscribeDataChanges,监听永久节点的数据变化)。当主机A进行了缓存更新后同时对ZNode中的对应数据进行变更,其他ZNode监听到后,就对本机具体的配置值进行缓存更新就可以保证整个集群缓存一致了。
#mermaid-svg-6OZ5EdGUKA70SsY7 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-6OZ5EdGUKA70SsY7 .error-icon{fill:#552222;}#mermaid-svg-6OZ5EdGUKA70SsY7 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-6OZ5EdGUKA70SsY7 .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-6OZ5EdGUKA70SsY7 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-6OZ5EdGUKA70SsY7 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-6OZ5EdGUKA70SsY7 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-6OZ5EdGUKA70SsY7 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-6OZ5EdGUKA70SsY7 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-6OZ5EdGUKA70SsY7 .marker.cross{stroke:#333333;}#mermaid-svg-6OZ5EdGUKA70SsY7 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-6OZ5EdGUKA70SsY7 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-6OZ5EdGUKA70SsY7 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-6OZ5EdGUKA70SsY7 .actor-line{stroke:grey;}#mermaid-svg-6OZ5EdGUKA70SsY7 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-6OZ5EdGUKA70SsY7 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-6OZ5EdGUKA70SsY7 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-6OZ5EdGUKA70SsY7 .sequenceNumber{fill:white;}#mermaid-svg-6OZ5EdGUKA70SsY7 #sequencenumber{fill:#333;}#mermaid-svg-6OZ5EdGUKA70SsY7 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-6OZ5EdGUKA70SsY7 .messageText{fill:#333;stroke:#333;}#mermaid-svg-6OZ5EdGUKA70SsY7 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-6OZ5EdGUKA70SsY7 .labelText,#mermaid-svg-6OZ5EdGUKA70SsY7 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-6OZ5EdGUKA70SsY7 .loopText,#mermaid-svg-6OZ5EdGUKA70SsY7 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-6OZ5EdGUKA70SsY7 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-6OZ5EdGUKA70SsY7 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-6OZ5EdGUKA70SsY7 .noteText,#mermaid-svg-6OZ5EdGUKA70SsY7 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-6OZ5EdGUKA70SsY7 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-6OZ5EdGUKA70SsY7 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-6OZ5EdGUKA70SsY7 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-6OZ5EdGUKA70SsY7 .actorPopupMenu{position:absolute;}#mermaid-svg-6OZ5EdGUKA70SsY7 .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-6OZ5EdGUKA70SsY7 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-6OZ5EdGUKA70SsY7 .actor-man circle,#mermaid-svg-6OZ5EdGUKA70SsY7 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-6OZ5EdGUKA70SsY7 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}
主机A
ZK
其他主机
注册永久节点ZkClient.createPersistent
注册永久节点ZkClient.createPersistent
注册监听ZkClient.subscribeDataChanges
注册监听ZkClient.subscribeDataChanges
我更新了配置值缓存 为XXX
监听到有主机更新了配置值为XXX,更新本地缓存值为XXX
主机A
ZK
其他主机
版权归原作者 伯子南 所有, 如有侵权,请联系我们删除。