bachelor
Vladimir Protsenko 11 months ago
parent 4a071ac5aa
commit 00a4f61990

@ -1,684 +0,0 @@
# Введение
Крупномасштабным распределённым приложениям требуются различные формы синхронизации для достижения консенсуса о базовой информации окружения. Выделение примитивов синхронизации в API позволяет выделить ядро координации из логики приложения в отдельный сервис. Являясь частью критической инфраструктуры, к такому сервису предъявляются в первую очередь требования надёжности и доступности. Подобный дизайн делает разработку и поддержку распределённого приложения проще.
ZooKeeper является проектом с открытым исходным кодом, который предоставляет отказоустойчивый распределённый сервис хранения критичных для работы кластера данных. Хранимыми данными могут быть: конфигурационная информация, иерархическое пространство имён, url ссылки, идентификаторы задач и прочее. ZooKeeper, созданный для внутренних нужд компании Yahoo!”, в настоящее время стал использоваться такими открытыми технологиями, как: Apache HBase, HDFS, Apache Storm, Apache Kafka и др.
Сайт проекта http://zookeeper.apache.org/.
Статья: Hunt P. et al. ZooKeeper: Wait-free Coordination for Internet-scale Systems //USENIX annual technical conference. 2010. Т. 8. №. 9.
# Цель работы
- запустить ZooKeeper,
- изучить директорию с установкой ZooKeeper,
- запустить интерактивную сессию ZooKeeper CLI и освоить её команды,
- научиться проводить мониторинг ZooKeeper,
- разработать приложение с барьерной синхронизацией, основанной на ZooKeeper,
- запустить и проверить работу приложения.
Данная лабораторная может выполняться на виртуальной машине создаваемой по Vagrant конфигурации в приложении А или с ZooKeeper, установленным в Windows.
# Изучение ZooKeeper
## Установка
Данный шаг может быть пропущен, если вы будете работать с Vagrant.
Перейдите на страницу Download на официальном сайте https://zookeeper.apache.org/ и скачайте последнюю стабильную версию (на момент написания 3.4.14).
Архив содержит скрипты как для Windows, так и для Unix операционных систем. Необходимым условием для работы Zookeeper является наличие в системе Java Runtime Environment.
Распакуйте архив в директорию `С:\Temp` в Windows. Если вы используете Unix систему, распакуйте и переместите содержимое архива в `/opt`. Набор команд, устанавливающих ZooKeeper в CentOS 7, вы можете найти в Vagrantfile из приложения А.
Перед первым запуском переименуйте файл `zoo_sample.cfg` в директории `conf` в `zoo.cfg`. Файл `zoo.cfg`, который на данный момент содержит базовые настройки, используется для конфигурации сервера.
*Примечание.* В Windows системе в `Панель управления\Система и безопасность\Система -> Дополнительные параметры системы -> Переменные среды` можно установить `JAVA_HOME`, если она не была сконфигурирована вами или администратором после установки Java в систему.
## Запуск
### Windows
В Windows запустите сервер двойным кликом по скрипту `zkServer.cmd` в папке `./bin/` или из терминала, набрав:
```
zkServer.cmd
```
### Linux
```
zkServer.sh
```
Проверьте, что zookeeper работает
```
systemctl status zookeeper
```
## Изучение директории установки ZooKeeper
Перейдите в директорию установки ZooKeeper.
Изучите содержимое директории.
В директории находятся следующие папки:
- bin с исполняемыми файлами для запуска, остановки и взаимодействия с ZooKeeper,
- conf с конфигурационными файлами,
- contrib с инструментами для интеграции ZooKeeper в другие системы: rest, fuse, perl и python библиотеки,
- dist-maven артефакты Maven,
- docs в которой хранится документация,
- recipes различные рецепты, помогающие решать задачи с использованием ZooKeeper (выбор лидера, блокировки, очереди),
- src с исходным кодом и тестовыми скриптами.
## Взаимодействие с ZooKeeper через командный интерфейс CLI
Одним из способов взаимодействия с ZooKeeper является консольный интерфейс ZooKeeper CLI. В реальных задачах вы скорее всего будете использовать ZooKeeper клиентскую библиотеку, однако взаимодействие через CLI является прекрасной возможностью изучить систему и также полезно для ряда задач.
Прежде всего нам понадобится перейти в папку bin директории установки ZooKeeper.
Для запуска интерактивной сессии ZooKeeper CLI используйте скрипт zkCli с расширением в зависимости от той среды, в который вы его запускаете (sh - unix, cmd - windows).
Следующая команда устанавливает подключение к ZooKeeper CLI сессии:
```
./zkCli.sh -server 127.0.0.1:2181
```
*Примечание.* При запуске zkCli.sh без параметров по умолчанию подключение производится к localhost:2181, поэтому явно указанные выше параметры вы можете опустить.
Подключение установлено. Для вывода всех возможных команд наберите help.
```
[zk: localhost:2181(CONNECTED) 0] help
ZooKeeper -server host:port -client-configuration properties-file cmd args
addWatch [-m mode] path # optional mode is one of [PERSISTENT, PERSISTENT_RECURSIVE] - default is PERSISTENT_RECURSIVE
addauth scheme auth
close
config [-c] [-w] [-s]
connect host:port
create [-s] [-e] [-c] [-t ttl] path [data] [acl]
delete [-v version] path
deleteall path [-b batch size]
delquota [-n|-b|-N|-B] path
get [-s] [-w] path
getAcl [-s] path
getAllChildrenNumber path
getEphemerals path
history
listquota path
ls [-s] [-w] [-R] path
printwatches on|off
quit
reconfig [-s] [-v version] [[-file path] | [-members serverID=host:port1:port2;port3[,...]*]] | [-add serverId=host:port1:port2;port3[,...]]* [-remove serverId[,...]*]
redo cmdno
removewatches path [-c|-d|-a] [-l]
set [-s] [-v version] path data
setAcl [-s] [-v version] [-R] path acl
setquota -n|-b|-N|-B val path
stat [-w] path
sync path
version
whoami
```
Выйти из консоли вы можете с помощью команды quit или отправив EOF символ сочетанием Ctrl+D.
Далее последует изучение возможностей CLI интерфейса. Вы научитесь добавлять и удалять разные типы узлов znode, считывать и записывать данные в znode из CLI, разбираться в управлении конфигурациями на базовых примерах.
Находясь в консоли CLI введите команду `ls /`.
```
[zk: localhost:2181(CONNECTED) 2] ls /
[zookeeper]
```
В результе вы должны получить список узлов в корне иерархической структуры данных ZooKeeper. В данном случае выводится один узел. Аналогично вы можете изучать некорневые узлы. Выведите список дочерних узлов `/zookeeper`.
*Примечание.* Используйте автоматическое дополнение при наборе, срабатываемое по нажатию клавиши TAB.
Теперь в корне создайте свой узел `/mynode` с данными "first_version" следующей командой:
```
create /mynode 'first_version'
```
Проверьте, что в корне появился новый узел.
```
[zk: localhost:2181(CONNECTED) 4] ls /
[mynode, zookeeper]
```
Следующие команды возвращают данные и метаданные узла:
```
get /mynode
stat /mynode
```
```
[zk: localhost:2181(CONNECTED) 10] get /mynode
first_version
[zk: localhost:2181(CONNECTED) 13] stat /mynode
cZxid = 0x2
ctime = Wed Sep 01 10:51:29 SAMT 2021
mZxid = 0x2
mtime = Wed Sep 01 10:51:29 SAMT 2021
pZxid = 0x2
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 13
numChildren = 0
```
Изучим структуру, хранимую в узле
|Поле | Описание |
| ----| ----|
|'first_version'| Хранимые данные|
|cZxid| Номер транзакции создания узла в системе|
|ctime| Время создания узла|
|mZxid| Номер транзакции модификации узла|
|mtime| Время модификации узла|
|pZxid| Номер транзакции модификации дочерних узлов|
|cversion| Количество изменений дочерних узлов|
|dataVersion| Количество изменений данных узла|
|aclVersion| Количество изменений прав доступа к данному узлу|
|ephemeralOwner| Идентификатор сессии владельца узла, если узел эфимерный. Иначе значение равно нулю.|
|dataLength| Размер данных|
|numChildren| Количество дочерних узлов|
Измените данные узла на "second_version":
```
set /mynode 'second_version'
```
```
[zk: localhost:2181(CONNECTED) 15] get /mynode
second_version
[zk: localhost:2181(CONNECTED) 16] stat /mynode
cZxid = 0x2
ctime = Wed Sep 01 10:51:29 SAMT 2021
mZxid = 0x3
mtime = Wed Sep 01 10:56:11 SAMT 2021
pZxid = 0x2
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 14
numChildren = 0
```
В качестве результата мы получим обновлённые метаданные узла. Обратите внимание на те значения, которые изменились.
Изменилась дата модификации `mtime` и значение поля `dataVersion` стало больше на единицу, так как мы провели одно изменение. Также изменился размер данных.
Теперь создайте два нумерованных (sequential) узла в качестве дочерних mynode:
```
create -s /mynode/child 'im_sequential'
create -s /mynode/child 'me_too'
```
```
[zk: localhost:2181(CONNECTED) 17] create -s /mynode/child 'im_sequential'
Created /mynode/child0000000000
[zk: localhost:2181(CONNECTED) 18] create -s /mynode/child 'me_too'
Created /mynode/child0000000001
```
Передав дополнительно флаг -s, мы указали, что создаваемый узел нумерованный. Этот способ позволяет создавать узлы с уникальными именами, по которым можно узнать порядок поступления запросов на сервер.
*Пример.* Принадлежность клиентов к группе
Несмотря на то, что ZooKeeper используется, как правило, из программного кода, мы можем эмулировать простой сценарий мониторинга принадлежности клиентов к группе в CLI.
В данном примере в корне zookeeper файловой системы будет создан узел под именем mygroup. Затем несколько сессий CLI будут эмулировать клиентов, добавляющих себя в эту группу. Клиент будет добавлять эфимерный узел в mygroup иерархию. При закрытии сессии узел автоматически будет удаляться.
*Примечание.* При использовании Vagrant управляемой виртуальной машины из VisualCode создайте несколько терминалов и установите ssh соединение в каждом командой `vagrant ssh`.
Этот сценарий может применяться для реализации сервиса разрешения имён (DNS) узлов кластера. Каждый узел регистрирует себя под своим именем и сохраняет свой url или ip адрес. Узлы, которые временно недоступны или аварийно завершили работу, в списке отсутствуют. Таким образом директория хранит актуальный список работающих узлов с их адресами.
Внутри CLI сессии, создайте узел mygroup.
```
create /mygroup 'top_node'
```
Откройте две новых CLI консоли и в каждой создайте по дочернему узлу в mygroup:
*Примечание.* Удобный способ открыть CLI консоль в windows `Shift + Правая кнопка мыши -> Открыть окно PowerShell здесь` в директории zookeeper, затем выполнить `bin/zkCli.cmd`.
Консоль 1 - grue.
```
create -e /mygroup/grue 'iam_grue'
```
Консоль 2 - bleen.
```
create -e /mygroup/bleen 'iam_bleen'
```
Эфимерный тип узла задаётся ключом `-e`.
Проверьте в исходной консоли, что grue и bleen являются членами группы mygroup.
![](images/1_.png)
Представим теперь, что одному из клиентов нужна информация о другом клиенте (к качестве клиентов могут выступать узлы кластера). Этот сценарий эмулируется получением информации командой `get`, которую мы уже запускали ранее. Выберите консоль grue и обратитесь к информации узла bleen.
```
get /mygroup/bleen
```
Информацией, которая хранится в узле клиента может быть url адрес клиента, либо любая другая информация требуемая для работы распределённого приложения.
Теперь эмулируйте аварийное отключение любого клиента. Нажмите сочетание клавиш Ctrl+D в одной из консолей, создавшей эфимерный узел.
Проверьте, что соответствующий узел пропал из mygroup. Изменение списка дочерних узлов может произойти не сразу — от 2 до 20 `tickTime`, значение которого вы можете посмотреть в `zoo.cfg`.
```
[zk: localhost:2181(CONNECTED) 53] ls /mygroup
[bleen, grue]
[zk: localhost:2181(CONNECTED) 54] ls /mygroup
[bleen, grue]
[zk: localhost:2181(CONNECTED) 55] ls /mygroup
[bleen, grue]
[zk: localhost:2181(CONNECTED) 56] ls /mygroup
[bleen, grue]
[zk: localhost:2181(CONNECTED) 57] ls /mygroup
[bleen, grue]
[zk: localhost:2181(CONNECTED) 58] ls /mygroup
[bleen, grue]
[zk: localhost:2181(CONNECTED) 59] ls /mygroup
[bleen, grue]
[zk: localhost:2181(CONNECTED) 60] ls /mygroup
[bleen]
[zk: localhost:2181(CONNECTED) 61]
```
Таким образом клиенты могут получать информацию о появлении и отключении других клиентов.
В заключении удалите узел `/mygroup`.
```
delete /mygroup
```
### Пример управления конфигурацией распределённого приложения
Хранение конфигурационной информации в ZooKeeper одно из наиболее популярных приложений. Мы будем эмулировать данную концепцию также с помощью CLI.
Использование ZooKeeper для хранения конфигурационной информации имеет два преимущества. Первое состоит в том, что новые клиенты могут узнавать конфигурацию кластера и определять свою роль самостоятельно. Второе преимущество заключается в возможности подписки на обновление конфигурационных параметров. Это позволяет динамически реагировать на изменения в конфигурации во время выполнения, что необходимо в режиме работы 24/7.
Создадим в корне узел "myconfig" в задачу которого будет входить хранение конфигурации. В нашем случае узел будет хранить строку `'sheep_count=1'`.
Во всех случаях, когда конфигурационная информация нашего гипотетического распределённого приложения будет изменяться, мы будем обновлять znode строкой с новым значением. Другим клиентам распределённого приложения достаточно проверять хранимые в этом узле данные.
Откройте новую консоль и подключитесь к ZooKeeper. Данная консоль будет играть роль физического сервера, который ожидает получить оповещение в случае изменения конфигурационной информации, записанной в `/myconfig` znode.
Следующая команда устанавливает watch-триггер на узел:
```
get /myconfig -w true
```
Вернитесь к первому терминалу и измените значение myconfig:
```
set /myconfig 'sheep_count=2'
```
Во втором терминале должно появиться оповещение об изменении данных!
```
[zk: localhost:2181(CONNECTED) 87]
WATCHER::
WatchedEvent state:SyncConnected type:NodeDataChanged path:/myconfig
```
Триггер сбрасывается после одного срабатывания, а значит его придётся 'взводить' каждый раз заново. Как правило, в приложении, в логике обработчика события присутствует такая процедура.
Удалите узел `/myconfig`. Проверьте, что эта команда выполнилась.
Примеры приложений:
- Эфимерные узлы в сочетании возможностью быть нумерованными позволяют реализовать механизм аварийного переключения https://ru.wikipedia.org/wiki/Аварийное_переключение, производить выбор лидера, обеспечивать координацию доступа к ресурсам.
- Асинхронная передача и рассылка сообщений.
Другие примеры использования ZooKeeper https://zookeeper.apache.org/doc/r3.4.5/recipes.html.
## Мониторинг ZooKeeper
ZooKeeper позволяет проводить мониторинг его состояния с использованием 4 буквенных команд: `conf`, `cons`, `stat` и других. Полный список команд доступен по адресу https://zookeeper.apache.org/doc/r3.7.0/zookeeperAdmin.html#sc_4lw .
**Примечание. С коммита https://github.com/apache/zookeeper/commit/5fe68506f217246c7ebd96803f9c78e13ec2f11a Zookeeper 4-буквенные команды отключены по умолчанию. Вы можете их включить при запуске сервера с параметром JVM `-Dzookeeper.4lw.commands.whitelist=*`.**
Команды можно отправлять на сервер из linux терминала с помощью утилит `echo` и `netcat`. Для некоторых linux систем `netcat` может быть вызван по сокращённому имени `nc`. Синтаксис команды:
```
echo <команда> | nc <имя или адрес хоста zookeeper> <порт>
```
В Windows вы можете установить подключение к zookeeper командой telnet
```
telnet <имя или адрес хоста zookeeper> <порт>
```
Для следующей команды сервер должен прислать ответ "imok", если он функционирует и доступен:
```
echo ruok | nc localhost 2181
```
Узнать версию zookeeper позволяет следующая команда:
```
echo stat | nc localhost 2181
```
Следующая команда возвращает конфигурационные параметры ZooKeeper сервера:
```
echo conf | nc localhost 2181
```
После выполнения распечатываются следующие параметры:
- порт клиента (`clientPort`),
- путь к директории, где хранятся данные (`dataDir`),
- путь к директории, где хранятся логи сервера (`dataLogDir`),
- интервал часов, указанный миллисекундах (`tickTime`),
- максимальное количество подключений к серверу (`maxClientCnxns`),
- минимальный и максимальный таймаут сессии (`minSessionTimeout`, `maxSessionTimeout`),
- идентификатор сервера.
Вышеперечисленные параметры могут быть указана в конфигурационном файле в директории conf (полный путь `/opt/ibm/biginsights/zookeeper/conf/`).
Отправьте команду `cons` для получения списка подключений всех клиентов с детальной информацией о сессиях.
```
echo cons | nc localhost 2181
```
Команды cons и conf дают детальную информацию. Для получения более общей информации используйте stat.
```
echo stat | nc localhost 2181
```
В распределённом варианте работы ZooKeeper команду dump для вывода текущих сессий и связанных с ними эфимерных узлов следует выполнять на узле-лидере. В текущей лабораторной работе все данные будут связаны с локально выполняемыми клиентскими процессами.
```
echo dump | nc localhost 2181
```
Для того, чтобы посмотреть информацию о watch-триггерах используйте команду wchs:
```
echo wchs | nc localhost 2181
```
Существуют и другие команды, найти которые вы можете в документации по администрированию ZooKeeper (Administrator's Guide).
На этом первая часть работы завершена.
# Разработка распределённого приложения
ZooKeeper поставляется с двумя клиентами для языков C и Java. В текущей лабораторной мы будем использовать Java API для реализации приложения с барьерной синхронизацией. Аналогия с животными и зоопарком позволит лучше понять концепты ZooKeeper.
Вы создадите зоопарк, который будет представлен корневым узлом `/zoo/`. Каждое животное, ваше приложение, будет входить в зоопарк, оно будет создавать дочерний эфимерный узел в зоопарке со своим именем. После того, как все животные будут в сборе, каждое начнёт бежать и остановится через определённый период времени. В конце приложения эфимерные узлы будут явно удалены.
## Настройка среды и проекта
Разработка распределённого приложения будет вестись на языке Scala в IDE IntelliJ Idea.
Создайте новый проект SBT аналогично тому, как это делалось в лабораторной работе 4. Дождитесь когда SBT инициализирует проект. Это может занять несколько минут.
Добавьте в качестве зависимости библиотеку ZooKeeper в `build.sbt` как `provided`. Определите версию ZooKeeper. Координаты библиотеки соответствующей версии вы можете найти в https://mvnrepository.com/.
![](images/2_.png)
*Примечание.* При указании zookeeper зависимости может потребоваться исключения из зависимостей: `com.sun.jdmk`, `com.sun.jmx`, `javax.jms`.
## Реализация логики приложения
Инициализируйте пакет `zoo` в папке `src/main/scala/`.
В пакете `zoo` создайте scala объект `Main` и поместите туда следующий код.
```scala
package zoo
object Main {
val sleepTime = 100
def main(args: Array[String]): Unit = {
println("Starting animal runner")
val Seq(animalName, hostPort, partySize) = args.toSeq
val animal = Animal(animalName, hostPort, "/zoo", partySize.toInt)
try {
} catch {
case e: Exception => println("Animal was not permitted to the zoo. " + e)
}
}
}
```
Этот код объявляет главный класс с методом `main`. Программа ожидает в качестве аргументов список: имя животного, адрес и порт zookeeper, размер группы животных. Далее следует создание объекта `Animal` на основе параметров: имя животного, адрес и порт zookeeper, путь к корневому узлу для узлов животных, величина группы животных. В конце метода main располагается try/catch блок, в котором будет выполняться код взаимодействующий с ZooKeeper.
*Примечание.* Приём, с помощью которого присваиваются списку имён переменных соответствующие значения списка аргументов, называется "сопоставление по шаблону" (pattern matching).
Нашей следующей задачей будет реализация класса `Animal` и заполнение тела try блока.
В методе enter объект `Animal` должен связываться с ZooKeeper, создавать эфимерный узел с именем `animalName` и подписываться на обновления группы `/zoo`.
```scala
animal.enter()
println(s"${animal.name} entered.")
```
Напишите цикл, в котором с интервалом sleepTime в миллисекундах печатается сообщение о работе процесса. Количество итераций может быть случайным.
```scala
for (i <- 1 to Random.nextInt(100)) {
Thread.sleep(sleepTime)
println(s"${animal.name} is running...")
}
animal.leave()
```
Перейдём к реализации класса Animal. Для удобства обращения к полям класса будем использовать case class. Инициализация Animal заключается в установлении соединения с ZooKeeper, определении переменных mutex и animalPath.
```scala
package zoo
import org.apache.zookeeper._
case class Animal(name:String, hostPort:String, root:String, partySize:Integer) extends Watcher {
val zk = new ZooKeeper(hostPort, 3000, this)
val mutex = new Object()
val animalPath = root+"/"+name
if (zk == null) throw new Exception("ZK is NULL.")
}
```
Для реакции на события от ZooKeeper класс должен реализовывать метод process интерфейса Watcher.
```scala
override def process(event: WatchedEvent): Unit = {
// код реакции на событие
}
```
Так как обработка событий и проверка условия барьера выполняются в разных потоках нам понадобится выполнять код методов в синхронизованном блоке. Синхронизация в Scala похожа на Java и выполняется на объекте-мьютексе. Ниже приведён пример блока синхронизации.
```scala
mutex.synchronized {
// код
}
```
Реализуем простую реакцию $-$ вывод на экран события.
```scala
override def process(event: WatchedEvent): Unit = {
mutex.synchronized {
println(s"Event from keeper: ${event.getType}")
}
}
```
Далее перейдём к реализации метода enter.
```scala
def enter():Boolean = {
// код создания узла и ожидания у барьера
}
```
В начале метода создайте эфимерный узел.
```scala
zk.create(animalPath, Array.emptyByteArray, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL)
```
Затем в синхронизованном блоке в цикле напишите код, ожидающий появления в корневом узле `/zoo` всех животных.
```scala
mutex.synchronized {
while (true) {
val party = zk.getChildren(root, this)
if (party.size() < partySize) {
println("Waiting for the others.")
mutex.wait()
println("Noticed someone.")
} else {
return true
}
}
}
return false
}
```
Реализуйте оставшийся метод, который вызывается в конце приложения и удаляет созданный в начале эфимерный узел с помощью метода `delete`.
## Проверка работоспособности приложения
Запустите несколько клиентов распределённого приложения и проверьте его работу.
![](images/3_.png)
*Примечание.* Перед запуском создайте корневой узел животных `/zoo`, если он ещё не создан.
*Примечание.* Убедитесь, что библиотеки, которые используются проектом (zookeeper, log4j и другие) находятся в области видимости `CLASSPATH`. Окружения этапов компиляции, тестирования и исполнения как правило различны.
## Упражнения
С использованием Zookeeper сервиса:
1. Решите проблему обедающих философов (каждый философ - отдельный процесс в системе)
2. Реализуйте двуфазный коммит протокол для high-available регистра (каждый регистр - отдельный процесс в системе)
# Приложение А. Инициализация виртуальной машины с помощью Vagrant
Для работы Vagrant необходим гипервизор Oracle VM VirtualBox. Для инициализации виртуальной машины поместите следующие файлы в пустую папку, находясь в ней откройте терминал и запустите команду `vagrant up`.
Vagrantfile
```Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :
# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure("2") do |config|
# The most common configuration options are documented and commented below.
# For a complete reference, please see the online documentation at
# https://docs.vagrantup.com.
# Every Vagrant development environment requires a box. You can search for
# boxes at https://vagrantcloud.com/search.
config.vm.box = "centos/7"
# config.vm.provider "virtualbox" do |vb|
# # Display the VirtualBox GUI when booting the machine
# vb.gui = true
#
# # Customize the amount of memory on the VM:
# vb.memory = "1024"
# end
#
# View the documentation for the provider you are using for more
# information on available options.
# Enable provisioning with a shell script. Additional provisioners such as
# Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the
# documentation for more information about their specific syntax and use.
config.vm.provision "file", source: "zookeeper.service", destination: "zookeeper.service"
config.vm.provision "shell", inline: <<-SHELL
yum install nc -y
yum install java-11-openjdk -y
yum install wget -y
wget http://apache-mirror.rbc.ru/pub/apache/zookeeper/zookeeper-3.4.14/zookeeper-3.4.14.tar.gz
tar zxf zookeeper-3.4.14.tar.gz
mv zookeeper-3.4.14 /opt/
cp /opt/zookeeper-3.4.14/conf/zoo_sample.cfg /opt/zookeeper-3.4.14/conf/zoo.cfg
mv zookeeper.service /etc/systemd/system/zookeeper.service
chmod 664 /etc/systemd/system/zookeeper.service
systemctl start zookeeper
SHELL
end
zookeeper.service
[Unit]
Description=Zookeeper
After=syslog.target
[Service]
SyslogIdentifier=zookeeper
TimeoutStartSec=10min
Type=forking
ExecStart=/opt/zookeeper-3.4.14/bin/zkServer.sh start
ExecStop=/opt/zookeeper-3.4.14/bin/zkServer.sh stop
[Install]
WantedBy=multi-user.target
```
# Дополнительные ссылки
1. https://www.youtube.com/c/DistributedSystemsCourse
2. https://www.youtube.com/c/lindseykuperwithasharpie
3. https://lamport.azurewebsites.net/video/videos.html (recent talk: https://www.youtube.com/watch?v=Ocxczi-CvRQ)
4. https://hydraconf.com/ (free talks: https://www.youtube.com/channel/UCcwI0q9tsGZYZDvz5mLsXZA)
5. Lynch, Nancy A. Distributed Algorithms. 1996. https://dl.acm.org/doi/book/10.5555/2821576
6. Martin Kleppmann. Designing Data-Intensive Applications: The Big Ideas Behind Reliable, Scalable, and Maintainable Systems
7. Alex Petrov. Database Internals: A Deep Dive Into How Distributed Data Systems Work.

@ -1,56 +0,0 @@
# Подсказки к упражениям
## Двухфазный коммит протокол на основе ZooKeeper
На основе материалов: https://zookeeper.apache.org/doc/r3.4.2/recipes.html#sc_recipes_twoPhasedCommit и https://stackoverflow.com/questions/24635777/how-to-implement-2pc-in-zookeeper-cluster
[![IMAGE_ALT](https://img.youtube.com/vi/yu2TZF7S1Mg/3.jpg)](https://youtu.be/yu2TZF7S1Mg?t=964)
Протокол двухфазной коммита — это алгоритм, позволяющий всем клиентам в распределенной системе договориться либо о коммите транзакции, либо о ее откате.
Взаимодействующие компоненты:
- создатель транзакции,
- координатор транзакции,
- исполнители транзакции,
- zookeeper,
- (опционально) прямой канал связи создателя транзакции и координатора,
- (опционально) прямые каналы связи между координатором и исполнителями.
### Вариант 1.
В ZooKeeper вы можете реализовать двухфазный коммит протокол, если координатор создаст узел транзакции, скажем "/app/Tx", и один дочерний узел для каждого исполнителя транзакции, скажем "/app/Tx/node_i". Когда *координатор* создает дочерний узел, он оставляет его содержимое неопределенным.
Первая фаза:
Как только каждый исполнитель, участвующий в транзакции, получает транзакцию от координатора, исполнитель читает каждый дочерний узел "node_i" и подписывается на события изменения транзакционного узла. Затем каждый исполнитель обрабатывает запрос и принимает решение "commit" или "abort", записывая данные в свой узел.
Вторая фаза:
Как только запись завершается, другие исполнители получают уведомление, и как только все исполнители получат все голоса, они могут принять решение либо "commit", либо "abort". Обратите внимание, что узел может принять решение абортировать транзакцию раньше, если какой-либо исполнитель проголосует за "abort".
Интересным аспектом этой реализации является то, что единственная роль координатора заключается в определении группы исполнителей, создании узлов ZooKeeper и распространении транзакции на соответствующим исполнителям. Фактически, даже распространение транзакции может быть сделано через ZooKeeper путем записи в узле транзакции.
У описанного выше подхода есть два важных недостатка:
— это сложность сообщений, которая составляет O(n²).
— невозможность обнаружения аварийного завершения исполнителей.
Для решения первой проблемы можно сделать так, чтобы об изменениях в узлах транзакций уведомлялся только координатор, а затем уведомлять исполнителей, как только координатор примет решение. Обратите внимание, что этот подход остаётся масштабируемым, но он медленнее, поскольку требует, чтобы все коммуникации проходили через координатора.
Для решения второй проблемы можно сделать так, чтобы координатор распространял транзакцию исполнителям, а каждый исполнитель создавал свой собственный эфемерный узел.
### Вариант 2.
1. Координатор C регистрирует транзакционный узел /app/tx
Первая фаза:
2. Координатор уведомляет исполнителей о транзакции
3. Координатор подписывается на изменения транзакционного узла (устанавливает WATCH на /app/tx)
4. Каждый исполнитель создает эфемерных узел /app/tx/node_i с решением commit/abort
5. Исполнитель подписывается на события своего узла для получения решения от координатора ( вторая фаза )
Вторая фаза:
6. Координатор принимает решение о commit/abort после ожидания таймаута или после создания всех узлов исполнителей с решением commit
7. Координатор изменяет значение эфемерных узлов для каждого исполнителя на commit / abort
8. Исполнители применяют / прерывают транзакцию
9. Исполнители обновляют значение узла на committed

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

@ -1,20 +1,16 @@
# Материалы курса "Большие данные" 2023 # Материалы курса "Большие данные" 2024 (бакалавры)
### График выполнения и форма отчётности ### График выполнения и форма отчётности
| Время | Лабораторная работа | Форма отчётности | | Время | Лабораторная работа | Форма отчётности |
| ------ | ------ | ------ | | ------ | ------ | ------ |
| Сентябрь | [Введение в Apache Spark](./L1%20-%20Introduction%20to%20Apache%20Spark/) | проект с выполненными заданиями и отчёт | | Февраль | [Введение в Mapreduce](./L0%20-%20Introduction%20to%20MapReduce%20data%20processing%20model/) | jupyter ноутбук с выполненными заданиями |
| Октябрь | [Формирование отчётов в Apache Spark](./L2%20-%20Reports%20with%20Apache%20Spark) | скрипт/проект и отчёт | | Март | [Введение в Apache Spark](./L1%20-%20Introduction%20to%20Apache%20Spark/) | jupyter ноутбук или проект с выполненными заданиями и отчёт |
| Ноябрь | [Потоковая обработка в Apache Flink](./L3%20-%20Stream%20processing%20with%20Apache%20Flink/README.md) | проект с выполненными заданиями и отчёт (с зелёными тестами) | | Апрель | [Формирование отчётов в Apache Spark](./L2%20-%20Reports%20with%20Apache%20Spark) | jupyter ноутбук или скрипт/проект и отчёт |
| Декабрь | [ZooKeeper](./L4%20-%20ZooKeeper/L4_Zookeeper.md) | проект и отчёт | | Май | [Потоковая обработка в Apache Flink](./L3%20-%20Stream%20processing%20with%20Apache%20Flink/README.md) | проект с выполненными заданиями и отчёт (с зелёными тестами) |
Первые две лабораторные могут выполняться на оборудовании университета на сайте https://mapr.space. Пишите, для регистрации пользователя, преподавателю. Spark лабораторные могут выполняться в Google Colab, наподобие того, как это сделано здесь https://colab.research.google.com/drive/1G894WS7ltIUTusWWmsCnF_zQhQqZCDOc.
### События В заданиях используйте выборки данных из папки [data](./data/) .
### Архив событий Для сдачи выкладывайте решения в репозиторий на github (или иной хостинг на основе системы контроля версий).
27-30 июня, Data + AI Summit NA 2022: https://databricks.com/dataaisummit/north-america-2022
26-28 октября, Flink Forward Global 2021: https://www.youtube.com/playlist?list=PLDX4T_cnKjD0J2LFr7yBk2aSS_o2l-7ue
24-28 мая, Data + AI Summit NA 2021: https://www.youtube.com/playlist?list=PLTPXxbhUt-YVtufaAKCRfyPYsjgpq5DRL
9-12 декабря, SmartData 2020: https://www.youtube.com/playlist?list=PLeN_80lmoMY1ugdDLg2mWht5eQDq6CoNQ
Loading…
Cancel
Save