Концепция BaselineTopology в Apache Ignite 2.4

    image


    На момент появления в Apache Software Foundation проекта Ignite он позиционировался как чистое in-memory-решение: распределенный кэш, поднимающий в память данные из традиционной СУБД, чтобы выиграть во времени доступа. Но уже в релизе 2.1 появился модуль встроенной персистентности (Native Persistence), который позволяет классифицировать Ignite как полноценную распределенную базу данных. С тех пор Ignite перестал зависеть от внешних систем обеспечения персистентного хранения данных, и вязанка граблей конфигурации и администрирования, на которые не раз наступали пользователи, исчезла.


    Однако persistent-режим порождает свои сценарии и новые вопросы. Как предотвратить неразрешимые конфликты данных в ситуации split-brain? Можем ли мы отказаться от перебалансировки партиций, если выход узла теперь не означает, что данные на нем потеряны? Как автоматизировать дополнительные действия вроде активации кластера? BaselineTopology нам в помощь.


    BaselineTopology: первое знакомство


    Концептуально кластер в in-memory-режиме устроен просто: выделенных узлов нет, все равноправны, на каждый можно назначить партицию кэша, отправить вычислительную задачу или развернуть сервис. Если же узел выходит из топологии, то запросы пользователей будут обслуживаться другими узлами, а данные вышедшего узла будут более недоступны.


    На самом деле, задать группы можно и в in-memory-режиме

    При помощи cluster groups и user attributes пользователь может на основе выбранных признаков распределять узлы по классам. Однако перезапуск любого узла заставляет его «забыть», что происходило с ним до перезапуска. Данные кэшей будут перезапрошены в кластере, вычислительные задачи исполнены повторно, а сервисы развернуты вновь. Раз узлы не хранят состояния, то они полностью взаимозаменяемы.


    В режиме персистентности узлы сохраняют свое состояние даже после перезапуска: в процессе старта данные узла считываются с диска, и его состояние восстанавливается. Поэтому перезагрузка узла не приводит к необходимости полного копирования данных с других узлов кластера (процесс, известный как rebalancing): данные на момент падения будут восстановлены с локального диска. Это открывает возможности для очень заманчивых оптимизаций сетевого взаимодействия, и в итоге вырастет производительность всего кластера. Значит, нам нужно как-то отличать множество узлов, способных сохранять своё состояние после перезапуска, от всех остальных. Этой задаче служит BaselineTopology.


    Стоит заметить, что пользователь может задействовать persistent-кэши одновременно с in-memory-кэшами. Последние будут продолжать жить той же жизнью, что и раньше: считать все узлы равноправными и взаимозаменяемыми, начинать перераспределение партиций при выходе узлов для поддержания количества копий данных — BaselineTopology будет регулировать только поведение persistent-кэшей.


    BaselineTopology (далее BLT) на самом верхнем уровне — это просто коллекция идентификаторов узлов, которые были сконфигурированы для хранения данных. Как создать BLT в кластере и управлять ею, разберемся чуть позже, а сейчас давайте посмотрим, какая от этой концепции польза в реальной жизни.


    Persisted-данные: разъезд запрещен


    Проблема распределенных систем, известная как split brain, и без того сложная, при использовании persistence становится еще более коварной.


    Простой пример: у нас есть кластер и реплицированный кэш.


    Кэши реплицированные и партицированные

    Стандартным подходом обеспечения отказоустойчивости является поддержание избыточности какого-либо ресурса. Ignite применяет этот подход для обеспечения надежности хранения данных: в зависимости от конфигурации кэш может хранить более одной копии ключа на разных узлах кластера. Реплицированный кэш хранит по одной копии на каждом узле, партицированный — фиксированное количество копий.
    Более подробно об этой функции можно узнать из документации.


    Произведем над ним простые манипуляции в следующей последовательности:


    1. Остановим кластер и запустим группу узлов A.
    2. Обновим какие-либо ключи в кэше.
    3. Остановим группу A и запустим группу Б.
    4. Применим другие обновления для тех же самых ключей.

    image


    Раз Ignite работает в режиме базы данных, то при остановке узлов второй группы обновления не потеряются: они станут доступны, как только мы снова запустим вторую группу. Так что после восстановления первоначального состояния кластера разные узлы могут иметь разные значения для одного и того же ключа.


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


    Предотвращение этой ситуации — как раз одна из задач BLT.


    Идея в том, что в режиме персистентности запуск кластера проходит через дополнительную стадию, активацию.


    При самой первой активации на диске создается и сохраняется первая BaselineTopology, которая содержит информацию обо всех узлах, присутствующих в кластере на момент активации.


    Эта информация включает в себя также хэш, вычисленный на основе идентификаторов online-узлов. Если при последующей активации некоторые узлы отсутствуют в топологии (например, кластер перезагружался, а один узел был выведен на обслуживание), то хэш вычисляется заново, а предыдущее значение сохраняется в истории активаций внутри этой же BLT.


    Таким образом, BaselineTopology поддерживает цепочку хэшей, описывающих состав кластера на момент каждой активации.


    На этапах 1 и 3 после запуска групп узлов пользователю придется явно активировать неполный кластер, и каждый online-узел обновит BLT локально, добавив в нее новый хэш. Все узлы каждой группы смогут вычислить одинаковые хэши, но в разных группах они будут разные.


    Вы уже могли догадаться, что произойдет дальше. Если узел попробует присоединиться к «чужой» группе, будет определено, что узел активирован независимо от узлов этой группы, и ему будет отказано в доступе.


    Стоит заметить, что этот механизм валидации не даёт полной защиты от конфликтов в ситуации Split-Brain. Если кластер разделился на две половины таким образом, что в каждой половине осталась хотя бы одна копия партиции, и переактивация половин не производилась, то всё равно возможна ситуация, когда в половины поступят конфликтующие изменения одних и тех же данных. BLT не опровергает CAP-теорему, но защищает от конфликтов при явных ошибках администрирования.


    Плюшки


    Кроме предотвращения конфликтов в данных, BLT позволяет реализовать парочку необязательных, но приятных опций.


    Плюшка №1 — минус одно ручное действие. Уже упомянутая выше активация должна была выполняться вручную после каждой перезагрузки кластера; средства автоматизации «из коробки» отсутствовали. При наличии BLT кластер может самостоятельно принять решение об активации.


    Хотя Ignite-кластер — эластичная система, и узлы могут добавляться и выводиться динамически, BTL исходит из концепции, что в режиме базы данных пользователь поддерживает стабильный состав кластера.


    image


    При первой активации кластера свежесозданная BaselineTopology запоминает, какие узлы должны присутствовать в топологии. После перезагрузки каждый узел проверяет статус других узлов BLT. Как только все узлы окажутся в режиме онлайн, кластер активируется автоматически.


    Плюшка №2 — экономия на сетевом взаимодействии. Идея, опять же, основана на допущении, что топология будет оставаться стабильной на протяжении длительного времени. Раньше выход узла из топологии даже на 10 минут приводил к запуску ребалансировки партиций кэшей для поддержания количества бэкапов. Но зачем тратить сетевые ресурсы и замедлять работу кластера, если проблемы с узлом решатся в течение минут, и он снова будет в онлайне. BaselineTopology как раз и оптимизирует это поведение.


    Теперь кластер по умолчанию предполагает, что проблемный узел скоро вернется в строй. Часть кэшей в течение этого времени будут работать с меньшим количеством бэкапов, однако к прерыванию или замедлению сервиса это не приведет.


    Управление BaselineTopology


    Что ж, один способ нам уже известен: BaselineTopology автоматически создается при самой первой активации кластера. При этом в BLT попадут все серверные узлы, которые на момент активации были в режиме онлайн.


    Ручное администрирование BLT осуществляется с помощью control-скрипта из дистрибутива Ignite, подробнее о котором можно почитать на странице документации, посвященной активации кластера.


    Скрипт предоставляет очень простой API и поддерживает всего три операции: добавление узла, удаление узла и установка новой BaselineTopology.


    При этом если добавление узлов — достаточно простая операция без особых подвохов, то удаление активного узла из BLT — задача более тонкая. Ее выполнение под нагрузкой чревато гонками, в худшем случае — зависанием всего кластера. Поэтому удаление сопровождается дополнительным условием: удаляемый узел должен быть в оффлайне. При попытке удалить online-узел, control-скрипт вернет ошибку и операция не будет запущена.


    Поэтому при удалении узла из BLT по-прежнему требуется одна ручная операция: остановка узла. Впрочем, этот сценарий использования явно не будет основным, так что дополнительные трудозатраты не слишком велики.


    Java-интерфейс для управления BLT еще проще и предоставляет всего один метод, позволяющий установить BaselineTopology из списка узлов.


    Пример изменения BaselineTopology с помощью Java API:


    Ignite ignite = /* ... */;
    IgniteCluster cluster = ignite.cluster();
    
    // Получаем BaselineTopology.
    Collection<BaselineNode> curBaselineTop = cluster.baselineTopology();
    
    for (ClusterNode node : cluster.topology(cluster.currentTopologyVersion())) {
        // Если мы хотем, чтобы данный узел был в BaselineTopology
        // (shouldAdd(ClusterNode) - пользовательская функция)
        if (shouldAdd(node)
            curTop.add(node);
    }
    
    // Обновляем BaselineTopology
    cluster.setBaselineTopology(curTop);

    Заключение


    Обеспечение целостности данных — важнейшая задача, которую должно решать любое хранилище данных. В случае распределенных СУБД, к которым относится Apache Ignite, решение этой задачи становится существенно сложнее.


    Концепция BaselineTopology позволяет закрыть часть реальных сценариев, в которых целостность данных может нарушиться.


    Другим приоритетом Ignite является производительность, и здесь BLT также позволяет заметно экономить ресурсы и улучшать время отклика системы.


    Функциональность Native Persistence появилась в проекте совсем недавно, и, без сомнения, будет развиваться, становиться надежнее, производительнее и удобнее в использовании. А вместе с ней будет развиваться и концепция BaselineTopology.

    GridGain

    92,00

    Компания

    Поделиться публикацией
    Комментарии 0

    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

    Самое читаемое