Synchronization Between Nodes

The following text is a partial translation of the original English article, performed by ChatGPT (gpt-3.5-turbo) and this Jekyll plugin:

Когда два или более программных модуля обращаются к одному и тому же ресурсу, необходима синхронизация. Это означает, что только один модуль должен работать с ресурсом в определенный момент времени. Без такой синхронизации возникают коллизии и конфликты. Это особенно актуально, когда речь идет о “ресурсах”, не поддерживающих атомарные транзакции.

Чтобы решить эту проблему и предотвратить конфликты, необходимо ввести еще один элемент в систему. Перед доступом к ресурсу все программные модули должны захватить блокировку у централизованного сервера. После завершения манипуляций с ресурсом модуль должен освободить блокировку. Пока блокировка захвачена одним модулем, другие модули не смогут ее захватить. Этот подход очень прост и хорошо известен. Однако, я не нашел ни одной облачной службы, которая предоставляла бы такую ​​систему блокировки и разблокировки через RESTful API. Поэтому я решил создать свою - stateful.co.

Вот практический пример. У меня есть веб-приложение на Java, размещенное на Heroku. Там работают три сервера (или “динамо”), на которых запущено одно и то же приложение .war. Зачем нужны три сервера? Потому что нагрузка на веб-трафик довольно высокая, и одного сервера недостаточно мощно. Поэтому мне нужно их три. Все они работают с одним и тем же приложением.

Каждое веб-приложение работает с таблицей в Amazon DynamoDB. Оно обновляет таблицу, добавляет новые элементы, иногда удаляет некоторые элементы и выбирает их. Пока все хорошо, но конфликты неизбежны. Вот пример типичного сценария взаимодействия между веб-приложением и DynamoDB (я использую jcabi-dynamo):

Логика здесь очевидна. Сначала я извлекаю элемент из таблицы posts, затем считываю его salary и изменяю его в соответствии с моим алгоритмом перерасчета. Проблема в том, что другой модуль может начать делать то же самое, пока я перерасчитываю. Он будет считывать то же самое начальное значение из таблицы и начнет точно такой же перерасчет. Затем он сохранит новое значение, и я тоже сохраню. В результате у нас будет изменена только один раз зарплата Джеффа, в то время как пользователи ожидают двукратного изменения, так как двое из них инициировали две транзакции с двумя разными веб-приложениями.

Правильный подход здесь заключается в “блокировке” таблицы DynamoDB сначала, еще до чтения зарплаты. Затем вносить изменения и, наконец, разблокировать ее. Вот как мне помогает stateful.co. Все, что мне нужно сделать, это создать новую именованную блокировку в веб-панели stateful.co, получить мои ключи аутентификации и изменить свой Java-код.

Как видите, я оборачиваю эту критическую транзакцию в Callable, которая будет выполняться в изоляции. Очевидно, что такой подход не гарантирует атомарности транзакции - если часть транзакции завершится неудачно, не будет автоматического отката, и таблица DynamoDB останется в “сломанном” состоянии.

Блокировки от stateful.co гарантируют изоляцию в использовании ресурсов, и вы можете использовать любой тип ресурсов, включая таблицы NoSQL, файлы, объекты S3, встроенное программное обеспечение и т. д.

Не забудьте добавить эту зависимость в мой pom.xml:

Конечно, вы можете сделать то же самое; сервис абсолютно бесплатный. И вы можете использовать любые другие языки, а не только Java. Кстати, если заинтересованы, можете внести свой вклад с помощью собственного SDK на предпочитаемом вами языке; я добавлю его в коллекцию GitHub.

Translated by ChatGPT gpt-3.5-turbo/42 on 2023-12-27 at 04:58

sixnines availability badge   GitHub stars