Приступая к работе с ZooKeeper, этого достаточно!

Java
Приступая к работе с ZooKeeper, этого достаточно!

карта разума

предисловие

Во многих случаях мы можем видеть ZooKeeper в различных фреймворках, таких как промежуточное ПО Kafka, фреймворк Dubbo, Hadoop и так далее. Почему вы повсюду видите ZooKeeper?

1. Что такое ZooKeeper

ZooKeeper — это распределенная система координации услуг., который предоставляет решение для согласованности распределенных данных на основе ZooKeeper.Структура данных, Наблюдатель, Механизм выборови другие характеристики, можетРеализовать публикацию/подписку на данные, мягкую балансировку нагрузки, службу именования, унифицированное управление конфигурацией, распределенную блокировку, управление кластероми Т. Д.

2. Зачем использовать ZooKeeper

ZooKeeper гарантирует:

  • Запросы на обновление выполняются последовательно. Запросы на обновление от одного и того же клиента выполняются последовательно в том порядке, в котором они были отправлены.
  • Атомарность обновления данных. Обновление данных выполняется успешно или не удается
  • Глобально уникальное представление данных. Независимо от того, к какому серверу подключается клиент, представление данных непротиворечиво.
  • в реальном времени. В течение определенного промежутка времени данные, считанные клиентом, являются последними.

3. Структура данных

Структура данных ZooKeeper очень похожа на файловую систему Unix.В целом ее можно рассматривать как дерево.Каждый узел называется ZNode, и каждый ZNodeОн может хранить данные 1M по умолчанию. Каждый ZNode можетопределяется уникальным путем. Как показано ниже:

При создании ZNode можно указать следующие четыре типа, в том числе:

  • ПОСТОЯННЫЙ, постоянный ZNode. После создания, даже если клиент отключится от сервера, он не будет удален, и исчезнет только в том случае, если клиент активно его удалит.
  • PERSISTENT_SEQUENTIAL, постоянный порядковый номер ZNode. Как и постоянные узлы, он не будет удален после отключения, а количество ZNodes будет автоматически увеличиваться.
  • EPHEMERAL, временный ZNode. Когда клиент отключится от сервера, ZNode будет удален.
  • EPEMERAL_SEQUENTIAL, временный порядковый номер ZNode. Как и в случае эфемерных узлов, разъединения удаляются, а количество ZNodes автоматически увеличивается.

4. Механизм уведомления о мониторинге

Наблюдатель основан наШаблон наблюдателямеханизм для реализации. Если нам нужно получать уведомления об изменении узла ZNode, мы можем использовать прослушиватель Watcher.

Клиент регистрирует znode, который должен получать уведомления, в ZooKeeper, устанавливая наблюдатель, и когда znode изменяется, ZooKeeper отправляет сообщение клиенту..

Этот механизм уведомления является одноразовым.. После запуска наблюдателя ZooKeeper удаляется из соответствующего хранилища. Если вам необходимо постоянно отслеживать изменения ZNode, вы можете настроить нового наблюдателя для регистрации в ZooKeeper после получения уведомления.

Существует много типов точек наблюдения, таких какМониторинг изменений данных ZNode, мониторинг изменений дочерних узлов ZNode, мониторинг создания или удаления ZNode.

V. Избирательный механизм

ZooKeeper — это среда приложений с высокой доступностью, поскольку ZooKeeper поддерживает кластеры. Когда ZooKeeper находится в состоянии кластера, файл конфигурации не определяет Master и Slave, но выбирает их внутренне при инициализации сервера ZooKeeper, генерируя один как ведущий и несколько как ведомые, и придерживаясь принципа половинной доступности.

Из-за принципа половинной доступности 5 серверов и 6 серверов фактически имеют максимально допустимое количество простоев, равное 3, поэтому для экономии затратКоличество серверов в кластере обычно устанавливается равным нечетному числу..

Если во время выполненияЕсли связь с лидером не может поддерживаться в течение длительного времени, снова будут проведены выборы для генерации нового лидера для обеспечения доступности услуги..

6. Первый опыт

первый вОфициальный сайтЗагрузите ZooKeeper, я использую версию 3.3.6 здесь.

Затем разархивируйте, скопируйте файл zoo_sample.cfg в каталог /conf и переименуйте его в zoo.cfg.

Измените значение dataDir в zoo.cfg и создайте соответствующий каталог:

Наконец, перейдите в каталог /bin для запуска.Я использую оконную систему, поэтому запустите zkServer.cmd и дважды щелкните по нему:

Если запуск прошел успешно, вы можете увидеть это диалоговое окно:

Для визуального интерфейса я рекомендую использоватьZooInspector, операция относительно проста:

6.1 Использование Java для подключения к ZooKeeper

Сначала введите зависимости Maven:

<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.4.6</version>
</dependency>

Затем мы пишем метод Main для работы:

    //连接地址及端口号
    private static final String SERVER_HOST = "127.0.0.1:2181";

    //会话超时时间
    private static final int SESSION_TIME_OUT = 2000;

    public static void main(String[] args) throws Exception {
        //参数一:服务端地址及端口号
        //参数二:超时时间
        //参数三:监听器
        ZooKeeper zooKeeper = new ZooKeeper(SERVER_HOST, SESSION_TIME_OUT, new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {
                //获取事件的状态
                Event.KeeperState state = watchedEvent.getState();
                //判断是否是连接事件
                if (Event.KeeperState.SyncConnected == state) {
                    Event.EventType type = watchedEvent.getType();
                    if (Event.EventType.None == type) {
                        System.out.println("zk客户端已连接...");
                    }
                }
            }
        });
        zooKeeper.create("/java", "Hello World".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        System.out.println("新增ZNode成功");
        zooKeeper.close();
    }

Создайте постоянный ZNode с путем /java и значением «Hello World»:

7. Обзор API

7.1 Создать

public String create(final String path, byte data[], List<ACL> acl, CreateMode createMode)

Объяснение параметра:

  • путь ZNode путь
  • данные, хранящиеся в ZNode
  • acl Контроль разрешений ACL
  • createMode Тип ZNode

Контроль разрешений ACL, ZooKeeper определяет три общих разрешения в классе ZooDefs.Ids:

/**
 * This is a completely open ACL.
 * 完全开放的ACL,任何连接的客户端都可以操作该属性znode
 */
public final ArrayList<ACL> OPEN_ACL_UNSAFE = new ArrayList<ACL>(Collections.singletonList(new ACL(Perms.ALL, ANYONE_ID_UNSAFE)));

/**
 * This ACL gives the creators authentication id's all permissions.
 * 只有创建者才有ACL权限
 */
public final ArrayList<ACL> CREATOR_ALL_ACL = new ArrayList<ACL>(Collections.singletonList(new ACL(Perms.ALL, AUTH_IDS)));

/**
 * This ACL gives the world the ability to read.
 * 只能读取ACL
 */
public final ArrayList<ACL> READ_ACL_UNSAFE = new ArrayList<ACL>(Collections.singletonList(new ACL(Perms.READ, ANYONE_ID_UNSAFE)));

createMode — это четыре упомянутых ранее типа ZNode:

public enum CreateMode {
    /**
     * 持久性ZNode
     */
    PERSISTENT (0, false, false),
    /**
     * 持久性自动增加顺序号ZNode
     */
    PERSISTENT_SEQUENTIAL (2, false, true),
    /**
     * 临时性ZNode
     */
    EPHEMERAL (1, true, false),
    /**
     * 临时性自动增加顺序号ZNode
     */
    EPHEMERAL_SEQUENTIAL (3, true, true);
}

7.2 Запрос

//同步获取节点数据
public byte[] getData(String path, boolean watch, Stat stat){
    ...
}

//异步获取节点数据
public void getData(final String path, Watcher watcher, DataCallback cb, Object ctx){
    ...
}

Параметр stat в синхронном методе getData() используется для получения возвращаемой информации об описании узла:

public byte[] getData(final String path, Watcher watcher, Stat stat){
    //省略...
    GetDataResponse response = new GetDataResponse();
    //发送请求到ZooKeeper服务器,获取到response
    ReplyHeader r = cnxn.submitRequest(h, request, response, wcb);
    if (stat != null) {
        //把response的Stat赋值到传入的stat中
        DataTree.copyStat(response.getStat(), stat);
    }
}

Используйте синхронный getData() для получения данных:

    //数据的描述信息,包括版本号,ACL权限,子节点信息等等
    Stat stat = new Stat();
    //返回结果是byte[]数据,getData()方法底层会把描述信息复制到stat对象中
    byte[] bytes = zooKeeper.getData("/java", false, stat);
    //打印结果
    System.out.println("ZNode的数据data:" + new String(bytes));//Hello World
    System.out.println("获取到dataVersion版本号:" + stat.getVersion());//默认数据版本号是0

7.3 Обновление

public Stat setData(final String path, byte data[], int version){
    ...
}

Стоит отметить, что третья версия параметра,Используя механизм CAS, это предотвращает одновременное обновление данных узла несколькими клиентами, поэтому номер версии необходимо передавать при обновлении, и каждое обновление делает номер версии +1., если сервер получит номер версии и обнаружит, что он несовместим, будет выдано исключение.

Поэтому вам нужно запросить номер версии перед обновлением, иначе вы не сможете обновиться, если не знаете текущий номер версии:

    //获取节点描述信息
    Stat stat = new Stat();
    zooKeeper.getData("/java", false, stat);
    System.out.println("更新ZNode数据...");
    //更新操作,传入路径,更新值,版本号三个参数,返回结果是新的描述信息
    Stat setData = zooKeeper.setData("/java", "fly!!!".getBytes(), stat.getVersion());
    System.out.println("更新后的版本号为:" + setData.getVersion());//更新后的版本号为:1

После обновления номер версии был увеличен:

Если параметр входящей версии равен «-1», он сообщает серверу zookeeper, что клиенту необходимо выполнить операцию обновления на основе последней версии данных. Но -1 — это не действительный номер версии, а идентификатор.

7.4 Удалить

public void delete(final String path, int version){
    ...
}
  • путь путь для удаления узла
  • версия номер версии

Здесь также необходимо передать номер версии, а номер версии можно получить, вызвав метод getData(), что очень просто:

Stat stat = new Stat();
zooKeeper.getData("/java", false, stat);
//删除ZNode
zooKeeper.delete("/java", stat.getVersion());

7.5 сторожевой механизм

Как упоминалось в третьем пункте выше, ZooKeeper может использовать механизм мониторинга уведомлений, когда ZNode изменится, он получит уведомление и обработает его. Основанный на механизме наблюдения, ZooKeeper может проделывать множество трюков. как пользоваться?

Механизм мониторинга уведомлений ZooKeeper можно разделить на три процесса:

① Наблюдатель за регистрацией клиентов ②Наблюдение за серверной обработкой ③ Клиент перезванивает клиенту Watcher.

Есть 4 способа зарегистрировать наблюдателя: новый ZooKeeper(), getData(), exists(), getChildren(). Ниже показано использование метода exists() для регистрации наблюдателя:

во-первыхНеобходимо реализовать интерфейс Watcher, создайте новый слушатель:

public class MyWatcher implements Watcher {
    @Override
    public void process(WatchedEvent event) {
        //获取事件类型
        Event.EventType eventType = event.getType();
        //通知状态
        Event.KeeperState eventState = event.getState();
        //节点路径
        String eventPath = event.getPath();
        System.out.println("监听到的事件类型:" + eventType.name());
        System.out.println("监听到的通知状态:" + eventState.name());
        System.out.println("监听到的ZNode路径:" + eventPath);
    }
}

Затем вызовите метод exists(), чтобы зарегистрировать прослушиватель:

zooKeeper.exists("/java", new MyWatcher());
//对ZNode进行更新数据的操作,触发监听器
zooKeeper.setData("/java", "fly".getBytes(), -1);

Затем вы можете увидеть распечатанную информацию в консоли:

Здесь мы можем видетьОбъект Event.EventType — это тип события., мы можем судить о типе события, а затем сотрудничать сСостояние уведомления Event.KeeperState, сделать связанную бизнес-обработку, каковы типы событий?

Откройте исходный код EventType и KeeperState, чтобы просмотреть:

//事件类型是一个枚举
public enum EventType {
    None (-1),//无
    NodeCreated (1),//Watcher监听的数据节点被创建
    NodeDeleted (2),//Watcher监听的数据节点被删除
    NodeDataChanged (3),//Watcher监听的数据节点内容发生变更
    NodeChildrenChanged (4);//Watcher监听的数据节点的子节点列表发生变更
}

//通知状态也是一个枚举
public enum KeeperState {
    Unknown (-1),//属性过期
    Disconnected (0),//客户端与服务端断开连接
    NoSyncConnected (1),//属性过期
    SyncConnected (3),//客户端与服务端正常连接
    AuthFailed (4),//身份认证失败
    ConnectedReadOnly (5),//返回这个状态给客户端,客户端只能处理读请求
    SaslAuthenticated(6),//服务器采用SASL做校验时
    Expired (-112);//会话session失效
}

7.5.1 Особенности наблюдателя

  • один раз. Как только наблюдатель сработает, ZK будет удален из соответствующего хранилища.
    zooKeeper.exists("/java", new Watcher() {
        @Override
        public void process(WatchedEvent event) {
            System.out.println("我是exists()方法的监听器");
        }
    });
    //对ZNode进行更新数据的操作,触发监听器
    zooKeeper.setData("/java", "fly".getBytes(), -1);
    //企图第二次触发监听器
    zooKeeper.setData("/java", "spring".getBytes(), -1);

  • Серийное исполнение. Процесс клиентского обратного вызова Watcher представляет собой процесс последовательной синхронизации, который должен обеспечивать порядок.
    zooKeeper.exists("/java", new Watcher() {
        @Override
        public void process(WatchedEvent event) {
            System.out.println("我是exists()方法的监听器");
        }
    });
    Stat stat = new Stat();
    zooKeeper.getData("/java", new Watcher() {
        @Override
        public void process(WatchedEvent event) {
            System.out.println("我是getData()方法的监听器");
        }
    }, stat);
    //对ZNode进行更新数据的操作,触发监听器
    zooKeeper.setData("/java", "fly".getBytes(), stat.getVersion());

Результат печатается, указывая, что сначала вызывается слушатель метода exists(), а затем вызывается слушатель метода getData(). Потому что метод exists() регистрируется первым.

  • Легкий. WatchedEvent — это наименьшая единица уведомления всего механизма уведомления Watcher ZK. WatchedEvent состоит из трех частей:Статус уведомления, тип события, путь к узлу. Уведомления наблюдателя сообщают клиенту только о том, что произошло, а не о конкретном содержании события.

напиши в конце

Я помню, как Ли Юнлэ, начальник станции Б, сказал:Ваша собственная жизнь может стать лучше только тогда, когда вы сделаете лучше жизнь большего числа людей.

Это предложение также является источником мотивации для меня, чтобы начать писать о технологическом обмене в этом году.Я надеюсь, что эта статья будет вам полезна~

знаменитый летчикУчитель Масказал:За возвращение в город взимается плата, а лайк бесплатный~

在这里插入图片描述