幂等性 幂等性如何保证
1幂等性
1.1定义
幂等性的概念来源于数学,意思是N变换和1变换的结果是一样的。在工程中,幂等性用来表示用户对同一操作发起的一个请求或多个请求的结果是一致的,不会出现多次点击带来的副作用。
幂等性包括第一个请求对资源有副作用,但许多后续请求不会对资源有副作用。
幂等函数关注的是将来多次请求的副作用,而不是结果。
网络超时等问题不在幂等讨论范围内。
幂等性是系统服务对外界的一种承诺,而不是实现,它承诺只要接口被成功调用,多个外部调用对系统的影响就会是一致的。声明为幂等的服务会认为外部调用失败是正常的,失败后会有重试。
1.2场景
在业务开发过程中,可能会出现由于网络震动导致无法接收请求,触发重试机制,或者前端抖动导致表单重复提交的情况。比如在交易系统中,用户提交的购物请求已经被服务器正确处理,但是服务器的退货结果却因为网络等原因丢失,导致客户端无法得知处理结果。如果是在网页上,一些不恰当的设计可能会让用户认为上一次操作失败,然后刷新页面,导致扣费被调用两次,账户被再次扣费。这时候就需要引入幂等接口。
我们以MySQL为例。只有第三种情况需要开发人员使用其他策略来确保幂等性:
以下是重复提交和幂等性之间的区别:
重复提交意味着在第一次请求成功的情况下,不满足幂等要求的服务会多次改变其状态。
幂等比较常用,当第一次请求失败或结果未知时,会发起多次请求,从而多次确认第一次请求成功,但不会因为多次请求而出现多次状态变化。
1.3幂等思维
引入幂等性将使服务器逻辑更加复杂。为了满足幂等服务的需求,逻辑中至少有两点:
首先,查询最后的执行状态,如果没有,就把它当作第一个请求。
在服务改变状态的业务逻辑之前,确保防止重复提交的逻辑。
幂等性可以简化客户端的逻辑处理,但会增加服务提供商的逻辑和成本。所以是否使用要根据具体场景来分析。因此,除了特殊的业务需求之外,不应该尽可能多地提供幂等接口。
添加了用于控制幂等性的附加业务逻辑,这使得业务功能变得复杂。
并行执行功能改为串行执行,降低了执行效率。
2幂等解
2.1前端设置
用户单击提交按钮后,我们可以将该按钮设置为不可用或隐藏。
前端限制很简单,但是有一个致命的错误。如果有知识的用户通过模拟网页请求重复提交请求,前端限制将被绕过。
2.2唯一索引
防止订单被多次插入的最简单直接的方法是创建一个唯一的索引,然后在插入时语句可能会略有不同。但目的是确保数据库中只有一条相同的记录。
方法一:给数据库添加一个唯一的索引,然后如果在执行过程中捕捉到了DuplicateKeyException,就知道是重复插入造成的,然后继续执行业务。
方法二:使用MySQL自带的关键字,实现不存在就插入,存在就更新的操作。此关键字不会删除原始记录。
方法replace into的主要功能类似于INSERT操作。replace into的底层是先删除数据再插入数据,这样会破坏索引,重新维护。请注意主键或唯一索引必须有效,否则只会添加替换为。
2.3复制表
删除重复表的机制是基于mysql唯一索引的特点,一般过程如下:
客户端首先请求服务器,服务器首先将请求信息存储在mysql去重表中,该表应根据请求的特殊字段之一建立唯一索引或主键索引。
判断插入是否成功,如果插入成功,继续进行后续业务请求。如果插入失败,则意味着当前请求已经执行。
2.4悲观锁定
方法1:简单的使用Java自带的syn或者锁锁来实现幂等性。核心点是将重要的执行部分从并行切换到串行。缺点是这个锁不能用于分布式场景,因为它跨越了JVM!此时,需要引入分布式锁。
序列化是依靠MySQL自带的操作数据库实现的。这里的重点是简单解释一下:
当线程A执行更新时,数据将锁定当前记录。当其他线程执行这一行代码时,它们将等待线程A释放锁,然后才能获取锁并继续后续操作。
提交事务后,会自动释放为更新而获取的锁。
这种模式的缺点是,如果业务处理耗时且并发,后续线程会长时间处于等待状态,占用大量线程,使这些线程处于无效等待状态。然而,web服务中的线程数量通常是有限的。如果大量线程由于获取更新锁而处于等待状态,不利于系统的并发操作。
2.5乐观锁定
2.6分布式锁
Redis中的Setnx操作用于设置分布式锁中幂等性的保障屏障。如果setnx成功,说明这是第一次插入数据,继续执行SQL语句就可以了。如果setnx失败,则意味着它已经被执行。
2.7令牌方案
这种方法分为两个阶段:令牌申请阶段和支付阶段。
第一阶段:进入订单提交页面前,订单系统需要根据用户信息向支付系统发送令牌请求,支付系统将令牌保存在Redis缓存中,供第二阶段支付。
第二阶段:订单系统用应用的令牌发起支付请求,支付系统将检查Redis中是否存在令牌。如果存在,则表示第一次发起支付请求,删除缓存中的令牌后开始支付逻辑处理;如果缓存中不存在,则表示请求非法。
其实这里的代币可以看作代币,支付系统根据代币确认插入的唯一性。token模式的不足是需要系统之间的两次交互,过程比上述方法复杂。
令牌引用