写点什么

Soul 学习笔记 --- 使用 zookeeper 实现数据同步(六)

用户头像
fightingting
关注
发布于: 2021 年 01 月 21 日

今天看下 zookeeper 怎么实现数据同步的。


首先查下 zookeeper 是什么,网上看了一些资料,大概明白了它的用处。


分布式系统有个 CAP 理论:


  • 一致性:在分布式环境中,一致性是指数据在多个副本之间是否能够保持一致的特性,等同于所有节点访问同一份最新的数据副本。在一致性的需求下,当一个系统在数据一致的状态下执行更新操作后,应该保证系统的数据仍然处于一致的状态。

  • 可用性:每次请求都能获取到正确的响应,但是不保证获取的数据为最新数据。

  • 分区容错性:分布式系统在遇到任何网络分区故障的时候,仍然需要能够保证对外提供满足一致性和可用性的服务,除非是整个网络环境都发生了故障。


一个分布式系统最多只能同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance)这三项中的两项。分布式系统中,P 是必须的,因此只能在 CP 和 AP 中选择,zookeeper 保证的是 CP,对比 spring cloud 系统中的注册中心 eruka 实现的是 AP。


zookeeper 保证了分布式环境下数据的一致性。我觉得 zookeeperredis 很像,虽然底层实现机制不一样,但他们主要就是为了存储数据,不过 zookeeper 有一个 watch 机制,类似于观察者模式,watch 流程是客户端向服务端某个节点路径上注册一个 watcher,同时客户端也会存储特定的 watcher,当节点数据或子节点发生变化时,服务端通知客户端,客户端进行回调处理。soul 网关使用 zookeeper 进行数据同步,就利用的这个机制。


soul-adminsoul-bootstrap 项目的 application-local.yml 文件设置使用 zookeeper 进行同步。


soul:  sync:#    websocket:#        enabled : true    zookeeper:        url: localhost:2181        sessionTimeout: 5000        connectionTimeout: 2000
复制代码


启动 soul-admin 时,会返回一个ZookeeperDataChangedListenerZookeeperDataInit 实例。



ZookeeperDataInit 就是在启动时,把 selectorrule 等数据写入 zookeeper,每当有数据变更,就会更新 zookeeper 节点。



soul-bootstrap 启动时,会去加载类 ZookeeperSyncDataConfiguration ,它会新建一个 ZookeeperSyncDataService 实例。


    public ZookeeperSyncDataService(final ZkClient zkClient, final PluginDataSubscriber pluginDataSubscriber,                                    final List<MetaDataSubscriber> metaDataSubscribers, final List<AuthDataSubscriber> authDataSubscribers) {        this.zkClient = zkClient;        this.pluginDataSubscriber = pluginDataSubscriber;        this.metaDataSubscribers = metaDataSubscribers;        this.authDataSubscribers = authDataSubscribers;        //监听 plugin,selector,rule        watcherData();        watchAppAuth();        watchMetaData();    }
private void watcherData() { final String pluginParent = ZkPathConstants.PLUGIN_PARENT; if (!zkClient.exists(pluginParent)) { //节点不存在,将数据写入节点 zkClient.createPersistent(pluginParent, true); } List<String> pluginZKs = zkClient.getChildren(ZkPathConstants.buildPluginParentPath()); for (String pluginName : pluginZKs) { watcherAll(pluginName); } //这里订阅了节点的变化。 zkClient.subscribeChildChanges(pluginParent, (parentPath, currentChildren) -> { if (CollectionUtils.isNotEmpty(currentChildren)) { for (String pluginName : currentChildren) { watcherAll(pluginName); } } }); }
复制代码


可以看到这个类会监听 selectorrule 等数据,如果它们在 soul-admin 发生变化,这里就能接收到,从而更新内存中的数据。


参考资料


zookeeper 教程


用户头像

fightingting

关注

还未添加个人签名 2018.09.17 加入

还未添加个人简介

评论

发布
暂无评论
Soul 学习笔记---使用 zookeeper 实现数据同步(六)