Авторские права принадлежат автору Для любой формы перепечатки, пожалуйста, свяжитесь с автором для получения разрешения и укажите источник.
Введение в распределенные транзакции
Транзакции, реализованные в распределенных системах, являются распределенными транзакциями Принципы CAP распределенных систем:
последовательность
Доступность
Допуск перегородки
Распределенные транзакции в основном обеспечивают согласованность данных, есть три разных принципа
сильная консистенция
слабая консистенция
возможная согласованность
JTA и ХА
Общая основа:
Менеджер транзакций
XA Resource
двухэтапная фиксация
Служба заказов отслеживает сообщения в очереди новых заказов, добавляет новые заказы после их получения и записывает сообщения в очередь оплаты новых заказов в случае успеха Процесс добавления новых заказов в середине использует управление транзакциями JTA. транзакция будет откатана и возобновлена не будет Записывать сообщения в очередь оплаты заказа; Другой пример - после успешного списания комиссии сервисом Пользователя он пишет сообщение в очередь тикетов переноса нового заказа.В это время сервис Билет обрабатывается или обработка не проходит.Во время этого процесса пользователь проверяет свой баланс и комиссия была успешно списана, но информация о билете отсутствует.В это время вы можете использовать метод сбоя транзакции и отката для отката один за другим, что называется слабой согласованностью, или вы можете отправить содержимое сбой обработки в очередь ошибок и решить ее путем ручной обработки, которая называется согласованностью в конечном счете.
Реализация распределенной транзакции Spring JTA
Вы можете использовать диспетчер транзакций JTA, предоставляемый сервером приложений, таким как JBoss.
Можно использовать менеджеры транзакций JTA, предоставляемые такими библиотеками, как Atomikos и Bitronix.
Реализация распределенной транзакции без Spring JTA
Почему бы не использовать JTA?
Поскольку JTA использует двухэтапный метод подачи документов, первый этап является предварительным, а второй — официальным. Когда при первом подтверждении происходит ошибка, вся транзакция откатывается, и транзакция может занять много времени, поскольку она должна работать с несколькими базами данных и несколькими ресурсами данных, поэтому пропускная способность может быть низкой по производительности.
Не применяйте JTA, отправьте две транзакции по очереди
Метод синхронизации транзакций для нескольких ресурсов
XA и финальная ресурсная игра
1.start message transaction
2.receive message
3.start JTA transaction on DB
4.update database
5.phase-1 commit on DB transaction
6.commit message transaction ##当这一步出现错误时,上面的因为是XA的第一次提交预备状态,所以可以rollback
7.phase-2 commit on DB transaction ##当这一步出现错误时,因为message不是XA方式,commit后无法rollback
Однако по сравнению с отказом от использования JTA возможности ошибок транзакций в значительной степени удалось избежать.
Поделиться ресурсом
Две источники данных имеют одинаковый базовый ресурс
Например, ActiveMQ использует БД в качестве базового хранилища ресурсов.
Используйте менеджер транзакций базы данных базы данных для управления фиксацией транзакций.
Поддержка источника данных требуется для указания базового метода хранения ресурсов.
сделать все возможное
Совершайте транзакции последовательно
может пойти не так
Прямая синхронизация транзакций через AOP или Listener
Лучшее усилие JMS: одна фиксация + повторная попытка
Применяется, когда одним из источников данных является MQ и транзакция начинается с чтения сообщений MQ.
Используйте механизм повтора сообщений MQ
Дублирующиеся сообщения необходимо учитывать при повторной попытке
Могут возникнуть проблемы: операции с базой данных будут повторяться, так как транзакция базы данных не использует управление транзакциями JTA, поэтому база данных была успешно зафиксирована; как этого избежать, нужно игнорировать сообщения повторной передачи, такие как проверка уникальности и другие средства.
управление цепочкой транзакций
определить цепочку транзакций
Несколько транзакций последовательно фиксируются в диспетчере транзакций
может пойти не так
Как выбрать (согласно требованиям соответствия)
Строго согласованные транзакции: JTA (наихудшая производительность, только в пределах одного сервиса)
Слабые, в конечном итоге непротиворечивые транзакции: одна фиксация с максимальной эффективностью, цепочки транзакций (разработайте соответствующие механизмы обработки ошибок)
Как выбрать (по сценарию)
MQ-DB: лучшая попытка, одна фиксация + повторная попытка
Несколько БД: управление цепочками транзакций
Несколько источников данных: связанные транзакции или другие методы синхронизации транзакций.
пример
Пример 1-БД-БД
Существует два источника данных, настроенные в Applications.Properties
public class CustomerService{
@Autowired
@Qualifier("userJdbcTemplate")
private jdbcTemplate userJdbcTemplate;
@Autowired
@Qualifier("orderJdbcTemplate")
private jdbcTemplate orderJdbcTemplate;
private static final String UPDATE_CUSTOMER_SQL;
private static final String INSERT_ORDER_SQL;
@Transactional #事务管理注解
public void createOrder(Order order){
userJdbcTemplate.update(UPDATE_CUSTOMER_SQL, order)
if(order.getTitle().contains("error1")){ #模拟异常出现
throw new RuntimeException("error1")
}
orderJdbcTemplate.update(INSERT_ORDER_SQL, order) #没有使用事务,直接提交
if(order.getTitle().contains("error2")){ #模拟异常出现
throw new RuntimeException("error2")
}
}
}
Подробности о вышеуказанном процессе: Из-за использования метки @Transactional выполняется в транзакции
То есть синхронизируется с Менеджером транзакций, но синхронизация здесь не синхронизация транзакций, а переключение на синхронизацию подключения к БД.
Специальное примечание: @Transactional Если настройка не выполняется, будет использоваться DataSource под аннотацией @Primart в классе DBConfiguration, и он будет использоваться для подключения к источнику данных.
spring DataSourceUtilsисходный код Spring DataSourceUtils использует существующее соединение, но контролирует только выпуск соединения с базой данных, а не транзакцию.
Пример 2-DB-DB.Chained Менеджер транзакций
Цепной менеджер транзакций находится в этой библиотеке.
Добавьте абзац в класс DBConfiguration
@Bean
public PlatformTransactionManager transactionManager(){
DataSourceTransactionManager userTM = new DataSourceTransactionManager(userDataSource()) #看似方法调用,实则从spring容器中获取
DataSourceTransactionManager orderTM = new DataSourceTransactionManager(orderDataSource())
# orderTM.setDataSource(orderDataSource()) 如果使用这种方式则不是从容器中去获取了,因为orderTM不是spring容器管理
ChainedTransactionManager tm = new ChainedTransactionManager(userTM, orderTM) ## order先执行,user后执行
return tm;
}
Используйте работу моделирования Debug Mode, первый порядок после совершения транзакции, когда второе пользовательские службы выполнения транзакций для MySQL остановлены, появляется как исключениеПерезапуск службы msyql, программа продолжает работать, в это время в таблице заказов БД есть еще одна запись, но пользовательская таблица не изменилась, первая транзакция заказа не откатилась, если служба mysql остановился при откате, по сути не имеет никакого эффекта, потому что сам по себе коммит отсутствует, а выполнен ли откат или нет, не имеет никакого значения.