zoukankan      html  css  js  c++  java
  • Soul 学习笔记---使用 zookeeper 实现数据同步(六)

    今天看下 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 教程

  • 相关阅读:
    使用Silverlight 实现工作流流程定义
    中国国内航线信息的可视化
    笨办法学R编程(5)
    笨办法学R编程(4)
    笨办法学R编程(3)
    香山杯部分WP
    PWNABLE 3x17
    PWNABLE dubblesort
    PWNABLE applestore
    pyc文件修复出题经历
  • 原文地址:https://www.cnblogs.com/fightingting/p/14305944.html
Copyright © 2011-2022 走看看