С ростом популярности архитектуры распределенных служб несколько логических операций, которые первоначально выполнялись в одном приложении, теперь разделены на удаленные вызовы между несколькими службами. Хотя сервисизация обеспечивает возможность горизонтального масштабирования нашей системы, проблема, связанная с этим, заключается в распределенных транзакциях.Несколько сервисов используют свои собственные независимо поддерживаемые базы данных, и они не находятся в одной и той же транзакции друг с другом. А выполняется успешно, но выполнение Б завершается неудачно, а транзакция А в это время зафиксирована и не может быть отброшена, что в конечном итоге приведет к проблеме несогласованности данных с обеих сторон; хотя имел место XA, распространяемый на основе двухфазная фиксация давным-давно Транзакции, но этот тип схемы требует глобальной блокировки ресурсов, что приводит к крайне низкой производительности, поэтому эвентуальная согласованность сообщений, TCC и т. д. постепенно выводятся позже.柔性事务Схема распределенных транзакций в этой статье в основном анализируетСхема окончательной согласованности на основе сообщений.
Общий поток обработки сообщений
- производитель сообщений отправляет сообщение
- MQ получает сообщение, сохраняет его и добавляет новую запись в хранилище.
- Вернуть ACK производителю
- Push-сообщение MQ соответствующему потребителю, а затем дождитесь, пока потребитель вернет ACK.
- Если потребитель сообщения успешно возвращает ACK в течение заданного времени, то MQ считает, что потребление сообщения прошло успешно, и удаляет сообщение в хранилище, то есть выполняется шаг 6; если MQ не получает ACK в течение заданного времени, он считает, что потребление сообщения не удалось, и попытается повторно отправить сообщение и повторить шаги 4, 5 и 6.
- MQ удалить сообщение
Проблемы согласованности при обычной обработке сообщений
В качестве примера возьмем создание заказа, система заказов сначала создает заказ (локальную транзакцию), а затем отправляет сообщение в нижестоящую обработку, если заказ создан успешно, но сообщение не отправлено, то все нижестоящие системы не могут это воспринять событие, и появятся грязные данные. ;
public void processOrder() {
// 订单处理(业务操作)
orderService.process();
// 发送订单处理成功消息(发送消息)
sendBizMsg ();
}
Если сначала отправляется сообщение заказа, а затем заказ создается, то возможно, что сообщение успешно отправлено, но при создании заказа происходит сбой.В это время нижестоящая система считает, что заказ был создан, также появятся грязные данные.
public void processOrder() {
// 发送订单处理成功消息(发送消息)
sendBizMsg ();
// 订单处理(业务操作)
orderService.process();
}
неправильная идея
На этом этапе некоторые учащиеся могут задаться вопросом, можем ли мы обрабатывать отправку сообщений и бизнес-обработку в одной и той же локальной транзакции.Если бизнес-сообщение не будет отправлено, локальная транзакция будет отменена, чтобы можно было решить согласованность отправки сообщений. , Что насчет сексуальности?
@Transactionnal
public void processOrder() {
try{
// 订单处理(业务操作)
orderService.process();
// 发送订单处理成功消息(发送消息)
sendBizMsg ();
}catch(Exception e){
事务回滚;
}
}
Анализ аномалий отправки сообщений
| возможный | последовательность |
|---|---|
| Заказ был успешно обработан, а потом вдруг вышел из строя, транзакция не была зафиксирована, а сообщение не было отправлено | последовательный |
| Заказ успешно обработан, по сетевым причинам или из-за простоя MQ сообщение не отправляется и транзакция откатывается. | последовательный |
| Заказ успешно обработан, и сообщение успешно отправлено, но MQ не может сохранить сообщение по другим причинам, и транзакция откатывается. | последовательный |
| Заказ успешно обработан, и сообщение успешно сохранено, но время обработки MQ истекает, поэтому подтверждение ACK не выполняется, что приводит к откату локальной транзакции отправителя. | непоследовательный |
Из анализа вышеизложенной ситуации мы видим, что используя обычные методы обработки, ни в коем случае нельзя гарантировать согласованность как обработки бизнеса, так и отправки сообщения, фундаментальные причины:Для удаленных вызовов конечным результатом может быть успех, неудача или тайм-аут; в случае тайм-аута конечным результатом обработчика может быть успех или неудача, о которых вызывающая сторона не может знать.У автора когда-то была аналогичная ситуация в проекте, звонилка сначала записывала данные локально, а потом инициировала вызов службы RPC, но из-за большого объема данных БД время обработки истекло, и звонилка сразу откатывалась после произошло исключение тайм-аута Локальные транзакции, в результате которых данные на стороне вызывающего объекта отсутствуют, но данные на стороне процессора были записаны, что в конечном итоге приводит к несогласованности бизнес-данных на обеих сторонах. Чтобы обеспечить согласованность данных с обеих сторон, мы можем найти новые прорывы только из других мест.
сообщение о транзакции
не решается традиционными методами消息生成者本地事务处理成功и消息发送成功Проблемы согласованности между ними, поэтому родились сообщения о транзакциях,Он реализует атомарность локальной транзакции генератора сообщений и отправки сообщения и гарантирует, что локальная транзакция генератора сообщений успешно обработана и сообщение успешно отправлено.最终一致性проблема.
Поток обработки сообщений о транзакциях
-
Разница между транзакционными сообщениями и обычными сообщениями заключается в процессе создания сообщения: производитель предварительно отправляет сообщение в MQ (это также называется отправкой половинных сообщений).
-
После того, как MQ получит сообщение и сохранит его первым, в хранилище будет добавлено новое состояние.
待发送Новости -
Затем верните ACK отправителю сообщения, в это время MQ не будет запускать событие отправки сообщения.
-
После успешной предварительной отправки сообщения производителем выполните локальную транзакцию.
-
Выполнить локальную транзакцию, после завершения выполнения отправить результат выполнения в MQ
-
MQ удалит или обновит статус сообщения в зависимости от результата
可发送 -
Если статус сообщения обновляется до
可发送, то MQ отправит сообщение потребителю, и потребление следующего сообщения будет таким же, как и для обычного сообщения.
будь осторожен: Поскольку MQ обычно гарантирует, что сообщение может быть доставлено успешно, если бизнес не возвращает результат ACK вовремя, это может вызвать проблему повторной доставки сообщения MQ.Следовательно, для схемы конечной согласованности сообщений потребители сообщений должны поддерживать идемпотентное потребление сообщений и не могут вызывать повторное потребление одного и того же сообщения.
Анализ исключений сообщений о транзакциях
| ненормальная ситуация | последовательность | Метод обработки исключений |
|---|---|---|
| Сообщения не хранятся, хозяйственные операции не выполняются | последовательный | никто |
место хранения待发送Сообщение успешно отправлено, но подтверждение не выполнено, в результате чего служба не выполняется (может быть из-за тайм-аута обработки MQ, нестабильности сети и т. д.). |
непоследовательный | MQ подтверждает результат бизнес-операции и обрабатывает сообщение (удаляет сообщение) |
место хранения待发送Сообщение успешно, ACK успешно, и бизнес выполнен (может быть успешным или неудачным), но MQ не получает окончательный результат бизнес-обработки производителя. |
непоследовательный | MQ подтверждает результат бизнес-операции и обрабатывает сообщение (обновляет статус сообщения в соответствии с результатом бизнес-обработки, если бизнес-выполнение успешно, сообщение доставляется, а в случае сбоя сообщение удаляется) |
Бизнес-процесс выполнен успешно, и результат отправляется в MQ, но сообщение об обновлении MQ завершается ошибкой, в результате чего статус сообщения остается待发送
|
непоследовательный | То же |
MQ, поддерживающий транзакционные сообщения
В настоящее время более распространенные MQ, такие как ActiveMQ, RabbitMQ, Kafka, RocketMQ и т. д., только RocketMQ поддерживает сообщения о транзакциях. По мнению автора, добавление Али сообщений о транзакциях в MQ в первые годы также было вызвано потребностями бизнеса Alipay. Поэтому, если мы хотим сильно полагаться на сообщение транзакции MQ для достижения окончательной согласованности сообщения, в текущей ситуации мы можем выбрать RocketMQ только для технического выбора. Выше мы также проанализировали нештатную ситуацию с сообщениями о транзакциях, то есть MQ, хранящиеся待发送, но MQ не может воспринимать окончательный результат восходящей обработки. Для RocketMQ его решение очень простое, то есть его внутренняя реализация будет иметь запланированную задачу, а состояние обучения ротации —待发送сообщение, а затем отправить запрос на проверку производителю, и производитель должен реализовать прослушиватель проверки. Содержимое прослушивателя обычно состоит в том, чтобы проверить, была ли соответствующая локальная транзакция успешной (обычно запрос к БД). Если она успешна, MQ будет установлено сообщение可发送, иначе удалите сообщение.
Часто задаваемые вопросы
-
В: Если предварительное сообщение не будет отправлено, бизнес не будет выполнен?
Ответ: Да, для решений, основанных на согласованности сообщений в конечном счете, на этот шаг обычно сильно полагаются.Если этот шаг не может быть гарантирован, в конечном итоге станет невозможным достижение согласованности в конечном счете.
-
Q: Зачем добавлять сообщение
预发送Механизм, добавление механизма повтора для публикации сообщений дважды, почему бы не использовать механизм повтора, если отправка не удалась после успешного бизнеса?Ответ: Если бизнес-выполнение прошло успешно, отправьте сообщение еще раз. Если в это время нет времени на отправку сообщения, бизнес-система не работает. После перезапуска системы она не записывает, было ли сообщение отправлено ранее, что приведет к успешному выполнению дела Сообщение не было отправлено в конце.
-
Если потребитель не потребляет, должен ли производитель откатиться?
Ответ: Для сообщений о транзакциях производитель не будет выполнять откат из-за сбоя потребления потребителем.Для приложений, использующих сообщения о транзакциях, они преследуютВысокая доступностьивозможная согласованность, если потребление сообщения не удается, MQ будет отвечать за повторную отправку сообщения до тех пор, пока потребление не будет успешным. Таким образом, сообщения о транзакциях нацелены на производственную сторону и на потребительскую сторону, согласованность потребительской стороны завершается с помощью механизма повторных попыток MQ.
-
Если потребительская сторона, потому чтоделовое исключениеЭто ведет к откату, значит, обе стороны не могут гарантировать последовательность в итоге?
Ответ. Схема конечной согласованности на основе сообщений должна гарантировать, что потребитель находится вОтсутствие препятствий для хозяйственной деятельности, он допускает только аномальные системные сбои и не допускает сбои в бизнесе.Например, если в вашем бизнесе возникает такая проблема, как NPE, из-за которой ваша сторона-потребитель не может выполнить транзакции, трудно достичь согласованности.
Поскольку не все MQ поддерживают сообщения о транзакциях, если мы не выберем RocketMQ в качестве MQ системы, сможем ли мы добиться согласованности сообщений в конечном итоге? Ответ положительный.
Возможная согласованность на основе локальных сообщений
基于本地消息的最终一致性программныйОсновной метод заключается в записи данных сообщения в БД при выполнении бизнес-операции, а запись данных сообщения и запись бизнес-данных должны быть завершены в одной и той же транзакции, что является предпосылкой и основной гарантией схемы. .. После того, как данные сообщения записаны, мы можем перейти к базе данных через запланированную задачу, чтобы изменить статус обучения как待发送сообщение, а затем доставить сообщение в MQ. В этом процессе может возникнуть вероятность сбоя доставки сообщения.重试机制Чтобы убедиться, что статус сообщения обновляется или сообщение очищается до тех пор, пока не будет успешно получено подтверждение ACK для MQ; и если потребление последующего сообщения не удается, это зависит от повторной попытки самого MQ для завершения и, наконец, достижения окончательная согласованность данных системы с обеих сторон пол.基于本地消息服务Хотя это решение может обеспечить окончательную согласованность сообщений, у него есть серьезный недостаток: когда каждая бизнес-система использует это решение, ей необходимо создать таблицу сообщений в соответствующей бизнес-базе данных для хранения сообщений. В ответ на эту проблему мы можем выделить эту функцию отдельно и превратить ее в службу сообщений для унифицированной обработки, что приводит к решению, которое мы обсудим ниже.
Возможная согласованность для независимых служб сообщений
独立消息服务最终一致性и本地消息服务最终一致性Самая большая разница заключается в том, что хранилище сообщений превращается в службу RPC.Этот процесс на самом деле представляет собой процесс моделирования процесса предварительной отправки сообщений транзакционных сообщений.Если предварительная отправка сообщения не удается, бизнес-производитель не будет выполняться.Поэтому , Для бизнеса производителя это сильно зависит от службы сообщений. К счастью, независимая служба сообщений поддерживает горизонтальное расширение, поэтому, пока развернуто несколько единиц и сформирован режим кластера высокой доступности, ее надежность может быть гарантирована. В службе сообщений также есть отдельное задание по расписанию, которое будет периодически тренироваться в течение длительного времени.待发送сообщение о состоянии черезпроверить компенсационный механизмЧтобы убедиться, что бизнес, соответствующий сообщению, успешен, если соответствующая бизнес-обработка успешна, измените сообщение на可发送, а затем доставьте его в MQ; если бизнес-обработка не удалась, просто обновите или удалите соответствующее сообщение. Следовательно, при использовании этой схемы производитель сообщений должен также реализовать службу проверки для службы сообщений, чтобы подтвердить сообщение. Для потребления сообщений эта схема такая же, как описанная выше обработка, обе из которых гарантируют, что сообщения потребляются через собственный механизм повторной передачи MQ.
Суммировать: после фиксации восходящей транзакции откат не рассматривается в сценариях на основе MQ. Сбой может быть вызван простоем сети и сервиса.В статье упоминается, что выполнение бизнеса является безбарьерным. Если нисходящий сервис долго не восстанавливается, то следует ставить будильник, есть несколько механизмов для решения некоторых проблем типа псориаза, если вышестоящее сообщение всегда не удается отправить (такой возможности в принципе не существует, если только код не поддельный ) такие Мы можем настроить механизм сигнализации в случае исключения, например, печать журналов, отправка SMS-сообщений, отправка электронных писем и сохранение ненормальных заказов в базе данных.Эти меры могут быть использованы для некоторых ненормальных заказов ниже по течению в то же время, а также может создать новую аномальную тему при возникновении аномалии.Сообщение предлагает ручное вмешательство в исправление данных.
Если эта статья была вам полезна, обратите внимание