Микросервисы и диспетчер транзакций, как решить проблему параллелизма

Я работаю над созданием микросервиса, который использует диспетчер транзакций, реализованный на основе Java Transaction API (JTA).

Мой вопрос: есть ли у Trasaction maanger возможность обрабатывать проблему параллелизма в сценариях распределенной базы данных.

Сценарий:

Предположим, что существует несколько запущенных экземпляров службы, и мы получаем два запроса на обновление суммы баланса на 10 в учетной записи. Первоначально в учетной записи может быть 100 долларов, и первый экземпляр получает это и увеличивает его до 10 долларов, но еще не зафиксирован.

В то же время второй экземпляр также получает аккаунт, который по-прежнему равен 100, и увеличивает его на 10 долларов, а затем фиксирует его, обновляя баланс до 110 долларов, а затем обслуживает одну учетную запись снова обновляет до 110 долларов.

К этому времени вы, должно быть, догадались, что баланс должен быть увеличен на 20 долларов, а не на 10. Нужно ли мне писать какой-то механизм исключения Optimistic lock, чтобы предотвратить описанный выше сценарий, или Transaction Manager, основанный на спецификации JTA, уже обеспечит такую ​​вещь не случится ?


person Praveen    schedule 07.08.2018    source источник
comment
Почему вы храните общую сумму? Почему бы не сохранить транзакции и не подвести итоги. Текущий баланс Si равен 100. Сервисный вызов 1 добавляет новую транзакцию 10, а второй добавляет еще 10. Отображение баланса отображает сумму всех транзакций и отображает 120. Нет необходимости в некоторой глобальной обработке транзакций.   -  person Konrad    schedule 07.08.2018
comment
Это классический пример, когда вам нужно справиться с оптимистической блокировкой. И в нем нет ничего ни о микросервисах, ни о распределенных транзакциях ... может быть, это поможет вам для начала ... baeldung.com/jpa-optimistic-locking   -  person Vadim    schedule 07.08.2018


Ответы (3)


имеет ли Trasaction maanger возможность обрабатывать проблему параллелизма в сценариях распределенной базы данных.

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

Чтобы ответить на ваш вопрос: нет, Transaction Manager обычно не занимается обработкой проблем, возникающих при одновременных обновлениях. Он использует очень наивный и простой (и часто наиболее значимый) подход: если после начала транзакции он обнаруживает, что состояние стало несогласованным (из-за одновременных обновлений), он просто поднимет его как исключение и откатит транзакцию. Если только он сможет установить, что все условия свойств ACID транзакции все еще действительны, он зафиксирует транзакцию.

person Bhaskar    schedule 07.08.2018

Для такого типа запросов вы можете обрабатывать через Optimistic Concurrency, где у вас будет столбец в базе данных (Timestamp) в качестве ссылки на номер версии.

Каждый раз, когда фиксируется изменение, оно изменяет значение временной метки.

Если два запроса попытаются зафиксировать изменение в одно и то же время, только один из них будет успешным, поскольку столбец версии (Timestamp) изменится, а затем запретит другому запросу выполнение его изменений.

person skjagini    schedule 07.08.2018
comment
Правильно ли я предполагаю, что Transaction Manager не будет обрабатывать описанный выше сценарий? - person Praveen; 07.08.2018
comment
Я не совсем уверен, как работает JTA, но если вы можете объединить Optimistic Concurrency с JTA, он может откатить ваши изменения, когда произойдет исключение (номер версии уже изменился из-за другого запроса) - person skjagini; 07.08.2018

Диспетчер транзакций (как реализация спецификации JTA) делает прозрачной работу над несколькими ресурсами. Это гарантирует, что все операции выполняются как единое целое. «Работа над несколькими ресурсами» означает, что приложение может вставлять данные в базу данных и тем временем отправлять сообщение брокеру JMS. Диспетчер транзакций гарантирует сохранение свойств ACID для этих двух операций. В упрощенной форме, когда транзакция завершается успешно, разработчик приложения может быть уверен, что обе операции были обработаны. Когда возникают какие-то проблемы, их обрабатывает диспетчер транзакций - возможно, вызовет исключение и откатит изменения данных. Таким образом, ни одна операция не была обработана. Это делает это прозрачным для разработчика приложения, которому не нужно заботиться об обновлении сначала базы данных, а затем JMS, и проверяет, действительно ли были обработаны все изменения данных или произошел сбой.

В целом спецификация JTA не была написана с учетом архитектуры микросервисов. Теперь это действительно зависит от дизайна вашей системы (!). Но если учесть, что у вас есть два микросервиса, каждый из которых имеет свой собственный диспетчер транзакций, то диспетчер транзакций не сможет помочь вам решить проблему с параллелизмом. Менеджеры транзакций не работают (обычно) при некоторой синхронизации. Вы работаете не с несколькими ресурсами из одного микросервиса (каков вариант использования диспетчера транзакций), а с одним ресурсом из нескольких микросервисов.

Поскольку есть один ресурс, это точка синхронизации для всех ваших обновлений. От него зависит, как он управляет параллелизмом. Учитывая, что это база данных SQL, это зависит от уровня изоляции, которую она использует (ACID - I = изоляция, см. https://en.wikipedia.org/wiki/ACID_(computer_science)). В вашем конкретном примере говорится о феномене потери обновлений (https://vladmihalcea.com/a-beginners-guide-to-database-locking-and-the-lost-update-phenomen/). Так же обе микросервисы пытаются обновить одну запись. Одним из решений для предотвращения этой проблемы является использование оптимистической / пезимистической блокировки (вы можете реализовать ее самостоятельно, например, с помощью временных меток, как указано выше), другое - использовать сериализуемый уровень изоляции в вашей базе данных, или вы можете спроектировать свое приложение так, чтобы не читать и обновление данных на основе того, что было прочитано в первый раз, но измените запрос sql с атомарным обновлением (или, возможно, есть другие стратегии, как работать с вашей моделью данных для достижения желаемого результата).

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

person chalda    schedule 18.09.2018