幂等的多种实现方式

幂等的多种实现方式

前言

当相同的接口相同参数被请求,我们希望只处理一次相同请求。

实现方式

查询操作

查询数据时,无论是查询单条数据,还是查询多条数据,数据返回结果都不会变,select是天然的幂等操作。

删除操作

删除操作也是幂等的,无论删除一条,还是删除多条数据,目的是将数据删除,当被删除当数据再次执行,结果也是一样的。

唯一索引

防止新增脏数据
当设置要新增的字段为唯一索引,或这个字段与另外的字段是组合索引时,当请求参数,新增字段一致时,数据库会通过索引机制视为失效。

token机制

相同请求只允许提交一次。

实现思路
  • 集群环境
    采用token加Redis(redis单线程,处理需要排队)。
  • 单JVM进程
    采用token加redis或token加jvm内存。
实现流程

主要使用RedisLock —— redis.setnx函数,所以我们要让请求生成统一的redisKey来存储,在这里,我们认为token即是redisKey。

  1. 首次请求服务器时,服务器根据请求参数生成唯一的token(redisKey
  2. 将这个唯一的key保存在redis或者jvm内存中(在使用JVM内存情况下),并设置key有效时间(根据业务设计)
  3. 服务器再次接收请求时,生成规则不变(根据请求参数生成唯一的redisKey),然后先根据redisKey删除redis中的对象,如果删除成功代表请求内容相同。

上面的例子适用两次请求,当发生3次并发,删除会失败,然后又创建一个相同的线程进行数据持久化处理。
并发环境下,可以使用Token令牌+分布式锁方式(待更新)

悲观锁

SQL - for update
示例:

select column_1,column_2....column_N from table where id = 'xxx' for update;

注意:id一定要是主键或者唯一索引,否则锁表会发生错误!!!!
注意:id一定要是主键或者唯一索引,否则锁表会发生错误!!!!
注意:id一定要是主键或者唯一索引,否则锁表会发生错误!!!!


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

乐观锁

乐观锁相对于悲观锁效率更高,因为乐观锁只有在更新表的时候会锁表,其他时候不会锁表,所以效率更高。

乐观锁实现方式
  • 通过version
UPDATE TABLE_NAME SET NAME=#name#, VERSION=VERSION+1 WHERE VERSION =#version#
  • 通过条件限制
UPDATE TABLE_NAME SET AVAI_AMOUNT=AVAI_AMOUNT-#SUBAMOUNT# WHERE AVAI_AMOUNT-#SUBAMOUNT# >= 0
标题描述
要求条件AVAI_AMOUNT-#SUBAMOUNT# >= 0 ,这个情景,适用于不用版本号,只更新做数据安全校验,适合校验库存模型(因为库存不会小于等于0)、扣分额、回滚份额等,这个效率更高。
注意乐观锁更新操作,最好用主键或者唯一索引来更新,这样是行锁,否则更新时会锁表

根据“注意”中的提示,上面的两条sql,可优化成下面的样子

-- 添加where id=
UPDATE TABLE_NAME SET NAME=#name#, VERSION=VERSION+1 WHERE ID=#id# AND VERSION =#version#
-- 添加where id=
UPDATE TABLE_NAME SET AVAI_AMOUNT=AVAI_AMOUNT-#subAmount# WHERE ID=#id# AND  AVAI_AMOUNT-#subAmount# >= 0

分布式锁

可参考分布式事务所的实现和设计思想,这里不作为详细解释,分布式锁在分布式多进程环境下时,会生成一个唯一“key”(redis和zookeeper都可实现),后续相同操作这个锁是不一致的,在比较长业务扭转中(处理业务较多的场景时),分布式锁可以锁住一整套业务对数据的更新操作,然后提交,失败回滚。
分布式锁的实现方式很多,也有不同的设计思想,请参照另外的博客:分布式事务(#待更新)

select + insert

并发不高的后台系统,或一些任务调度系统(job),可以先查询,在更新操作,以此完成业务操作。
注意:高并发场景这种方式并不适用。

状态机幂等

什么是状态机图
  • 状态机图(State Machine Diagram)用来显示状态机的图,包括简单的状态、转换和嵌套的复合状态等,一个典型的状态机图如下:
    在这里插入图片描述
  • 状态机图的基本元素包括:状态、转移、事件、伪状态和复合状态;
    在这里插入图片描述

理解状态机幂等,可以理解为我们本身有一整套流程,假定流程有多个状态,只能顺序或按照规定扭转状态(例如Activity),当当前执行状态不是这一步应该执行的,是不允许的,我是这么理解状态机幂等的。例如:状态需要按照 1->3->4->5 的顺序执行,当我执行完1直接到4,是不允许的,保证了有限的状态机幂等。

注意:在业务扭转流程过长时,要深入理解状态机,并构建状态机图,对业务实现和归根溯源更有帮助!!!

API如何保证接口幂等

举例说明
  • 同步数据的时候
    数据来源方调用API进行同步数据,必须传递sourceId(来源)、seq(来源序列号),API提供方,在接收数据之后用这两个字段作为联合索引插入到数据库,每次调用API的时候,先用这两个字段进行校验,保证不重复,这里来源序列号的生成方式可参考雪花算法或者其它唯一主键生成算法。
  • Spring Cloud 接口幂等实现
    Spring Cloud —— 接口幂等实现(#待更新)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值