Немного размышлений о создании ордеров для достижения идемпотентности

Архитектура

идемпотентная концепция


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

Если операция произвольно выполняется несколько раз, эффекты (или побочные эффекты) будут одинаковыми.


Идемпотентность создания заказа


Если пользователь размещает заказ дважды, приобретаемые товары остаются теми же.

Первый запрос: user1: купить продукт product1, второй запрос: user1: еще купить продукт product1;

Этот сценарий также очень распространен и требует создания двух заказов. Таким образом, кажется, что интерфейс для создания заказов не может быть идемпотентным, потому что в случае одних и тех же бизнес-данных все равно необходимо создать несколько заказов. Но в этой конструкции есть еще одна яма: что делать, если время ожидания интерфейса для создания заказа истекает? И если вызывающий абонент повторяет попытку, может оказаться, что пользователь действительно хочет разместить заказ, но система заказов фактически генерирует несколько заказов. Например:

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

Если интерфейс ордера не поддерживает идемпотентность, как поступить в этой ситуации? Есть два способа

Первый:

Когда вызывающая сторона вызывает интерфейс заказа и истекает время ожидания, она получает исключение. В это время, после того как вызывающая сторона перехватывает это исключение,不要进行重试操作了,调用订单的一个回滚接口,将订单取消掉。Хотя это кажется очень низким, некоторые люди все еще делают это.

Секунда:

Пусть система заказов предоставляет интерфейс запроса, успешно ли создан заказ, и запрос в соответствии с некоторыми ключевыми бизнес-полями.Если запрос был успешно создан, вызывающему абоненту не следует повторять попытку.

Были использованы две вышеуказанные схемы, но ни одна из них не достигла идемпотентности. На самом деле, для приведенного выше сценария нетрудно спроектировать идемпотентность. Уникальный идентификатор серийного номера может использоваться для определения того, является ли это одним и тем же запросом или транзакцией. Этот идентификатор обычно требуется иметь全局唯一性. Если клиент генерирует этот идентификатор, каждый запрос на создание заказа генерирует уникальный идентификатор. Так как же на его основе система заказов достигает идемпотентности? Обычно их два.

Первый:

Сначала сохраните этот идентификатор в таблице потоков и установите этот идентификатор в таблице потоков какUNIQUE KEY, Если при вставке возник конфликт, значит, запрос на создание заказа был обработан, и возвращается сразу результат предыдущей операции.

Секунда:

Прочитать таблицу потоков по идентификатору, если не читается, создать заказ и вставить таблицу потоков.

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

Рекомендуется использовать первое решение, так как счетчик проточной воды, кстати, должен быть вставлен.UNIQUE KEYсудить о характеристиках конфликта.

Теперь воспользуемся первой схемой, чтобы полностью описать весь процесс.

Когда вызывающая сторона вызывает интерфейс для создания заказа с идентификатором серийного номера, если есть тайм-аут, вызывающая сторона не знает, был ли заказ успешно создан или неудачно.В это время используйте同一个Серийный номер повторяется.Хотя система заказов получила два запроса, поскольку идентификатор серийного номера один и тот же, идемпотентная операция может быть выполнена в соответствии с серийным номером. И сообщите другой стороне, был ли заказ создан успешно или нет.

Здесь есть еще одна яма: если звонящий повторно сгенерирует серийный номер при повторной попытке, он не будет сохранен, и будет сгенерировано несколько заказов. Это может гарантировать только клиент.