Давайте поговорим об идемпотентной обработке в условиях высокой параллелизма и распределения.

задняя часть Государственный аппарат

Давайте сначала поговорим о концепции идемпотентности.

абстракция

幂等(idempotent、idempotence)是一个数学与计算机学概念,常见于抽象代数中。

В программировании характеристика идемпотентной операции заключается в том, что любое ее многократное выполнение имеет тот же эффект, что и однократное выполнение. Идемпотентная функция или идемпотентный метод — это функция, которая может многократно выполняться с одними и теми же параметрами и достигать одного и того же результата. Эти функции не влияют на состояние системы, и не нужно беспокоиться, что повторное выполнение вызовет изменения в системе. Например, функции getUsername() и setTrue() являются идемпотентными.

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

Приведу несколько примеров:

1.比如前端对同一表单数据的重复提交,后台应该只会产生一个结果

2.比如我们发起一笔付款请求,应该只扣用户账户一次钱,当遇到网络重发或系统bug重发,也应该只扣一次钱

3.比如发送消息,也应该只发一次,同样的短信如果多次发给用户,用户会崩溃

4.比如创建业务订单,一次业务请求只能创建一个,不能出现创建多个订单

Есть много других, и эти логики должны поддерживаться идемпотентными свойствами.

Технические решения для достижения идемпотентности

операция запроса

查询一次和查询多次,在数据不变的情况下,查询结果是一样的,select是天然的幂等操作。

удалить операцию

删除操作也是幂等的,删除一次和多次删除都是把数据删除。(注意可能返回结果不一样,删除的数据不存在
,返回0,删除的数据多条,返回结果多个)。

Уникальный индекс для предотвращения появления новых грязных данных

拿资金账户和用户账户来说,每个用户只能有一个资金账户,怎么防止给用户创建资金账户多个,那么给资
金账户表中的用户ID加唯一索引,在新增的时候只有一个能请求成功,剩下都会抛出唯一索引重复异常。比
如`org.springframework.dao.DuplicateKeyException`,这时候再查询一次就可以了,数据存在,返回结果

механизм токенов для предотвращения повторных отправок страниц

要求:页面的数据只能被点击提交一次

发生原因:由于重复点击或者网络重发,或者nginx重发等情况会导致数据被重复提交

解决办法:

    集群环境:采用token加redis
    
    单JVM环境:采用token加redis或token加jvm内存

处理流程:

    数据提交前要向服务的申请token,token放到redis或jvm内存,token有效时间
    
    提交后后台校验token,同时删除token,生成新的token返回

token特点:要申请,一次有效性,可以限流

注意:redis要用删除操作来判断token,删除成功代表token校验通过,如果用select+delete来校验token,
存在并发问题,不建议使用

пессимистический замок

获取数据的时候加锁获取

select * from table_xxx where id=’xxx’ for update;

注意:id字段一定是主键或者唯一索引,不然是锁表,会出事的。

悲观锁使用时一般伴随事务一起使用,数据锁定时间可能会很长,根据实际情况选用

оптимистическая блокировка

乐观锁只是在更新数据那一刻锁表,其他时间不锁表,所以相对于悲观锁,效率更高。

乐观锁的实现方式多种多样可以通过version或者其他状态条件:

1.通过版本号实现

update table_xxx set name=#name#,version=version+1 where version=#version#

2.通过条件限制

update table_xxx set avai_amount=avai_amount-#subAmount# where avai_amount-#subAmount# >= 0

要求:avai_amount-subAmount >=0
这个情景适合不用版本号,只更新是做数据安全校验,适合库存模型,扣份额和回滚份额,性能更高。

注意:乐观锁的更新操作,最好用主键或者唯一索引来更新,这样是行锁,否则更新时会锁表,上面两个sql改成下面的两个更好。

update table_xxx set name=#name#,version=version+1 where id=#id# and version=#version#

update table_xxx set avai_amount=avai_amount-#subAmount# where id=#id# and 
avai_amount-#subAmount# >= 0

Распределенная блокировка

Возьмем пример вставки данных.Если дистрибутив системный, то сложно построить глобальный уникальный индекс.Например нельзя определить уникальное поле.В это время можно ввести распределенную блокировку.Через третью- партийная система (redis или zookeeper), в бизнесе Система вставляет данные или обновляет данные, получает распределенные блокировки, затем выполняет операции, а затем освобождает блокировки Фактически, она предназначена для управления многопоточными параллельными операциями, а также решение, часто используемое в распределенных системах.

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

select + insert

Для фоновых систем с низким уровнем параллелизма или некоторых задач JOB для поддержки идемпотентности и поддержки повторного выполнения простой метод обработки заключается в том, чтобы сначала запросить некоторые ключевые данные, определить, были ли они выполнены, а затем выполнить бизнес-обработку.

注意: не используйте этот метод для основных процессов с высокой степенью параллелизма.

идемпотент конечного автомата

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

Примечание: бизнес-документы, такие как заказы, имеют длинный поток состояний.Необходимо глубоко понимать конечный автомат, который очень помогает улучшить возможности проектирования бизнес-систем.

Как обеспечить идемпотентность для API, предоставляющих внешние интерфейсы

Например, платежный интерфейс, предоставляемый UnionPay: необходимо подключиться к продавцу, чтобы отправить запрос на оплату с: источником, источником, серийным номером

source+seq — это уникальный индекс в базе данных для предотвращения множественных платежей (при одновременном выполнении может быть обработан только один запрос).

Особенности:

Для поддержки идемпотентных вызовов в интерфейсе есть два поля, которые необходимо передать: одно — исходный код, а другое — последовательный серийный номер источника.Эти два поля используются как совместный уникальный индекс в системе провайдера, так что когда третья сторона вызывает , сначала проверьте в локальной системе, был ли он обработан, и верните соответствующий результат обработки; если он не был обработан, выполните соответствующую обработку и верните результат. Обратите внимание, что для того, чтобы быть идемпотентным и дружелюбным, вы должны сначала проверить, был ли обработан бизнес.Если вы вставите его непосредственно в бизнес-систему без запроса, будет сообщено об ошибке, но на самом деле он был обработан.

Окончательное резюме:

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