Статьи

Синхронизация между узлами

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

значок

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

Никакое Отступление, Никакая Сдача (1986) Кори Юэн

Никакое Отступление, Никакая Сдача (1986) Кори Юэн

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

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

Table table = region.table("posts");
Item item = table.frame()
  .where("name", "Jeff")
  .iterator().next();
String salary = item.get("salary");
item.put("salary", this.recalculate(salary));

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

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

Sttc sttc = new RtSttc(
  new URN("urn:github:526301"), // my Github ID
  "9FF3-4320-73FB-EEAC" // my secret key!
);
Locks locks = sttc.locks();
Lock lock = locks.get("posts-table-lock");
Table table = region.table("posts");
Item item = table.frame()
  .where("name", "Jeff")
  .iterator().next();
new Atomic(lock).call(
  new Callable<Void>() {
    @Override
    public void call() {
      String salary = item.get("salary");
      item.put("salary", this.recalculate(salary));
      return null;
    }
  }
);

Как видите, я заключаю ту критическую транзакцию  Callable, которая будет выполняться изолированно. Этот подход, очевидно, не гарантирует атомарность транзакции — если часть транзакции завершится неудачно, автоматического отката не будет, и таблица DynamoDB останется в «поврежденном» состоянии.

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

Я не должен забывать добавить эту зависимость к моей  pom.xml:

<dependency>
  <groupId>co.stateful</groupId>
  <artifactId>java-sdk</artifactId>
</dependency>

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