接口幂等性实现方案

阅读: 评论:0

接口幂等性实现方案

接口幂等性实现方案

接口幂等性

1. 什么是接口幂等性

幂等源于数学,表达的是N次变换与1次变换的结果相同。如果一个方法调用一次和调用多次产生的效果是相同的。幂等函数或者幂等方法,是指可以使用相同参数执行,并能获得相同结果的函数,这些函数不会影响系统的状态,也不用担心重复执行会对系统造成改变。

2. HTTP维度

GET方法

HTTP GET 方法用于获取资源,不应有副作用,所以是幂等的。Select可以说是天生的幂等。

这里指的是N次和1次具有相同的副作用,而不是返回相同的数据。

DELETE方法

HTTP DELETE 方法用于删除资源,有副作用,但是它应该满足幂等性,调用一次和调用N次的副作用是相同的,删除一个文章不会造成其他数据的误删。

POST方法

HTTP POST 所对应的URI尾资源的接收者。发表一篇文章,两次相同的POST请求会在服务器端创建两份资源,所以POST方法不具备幂等性。

PUT方法

HTTP PUT 所对应的URI是创建或者更新资源。创建或者更新一个ID唯一的文章,对同一个URI进行多次PUT和一次PUT是相同的,因此PUT方法具有幂等性。

幂等性讨论:

  • RESTful风格:它把HTTP当成应用程协议,遵守HTTP协议的各种规定。
  • 另一种是在HTTP协议上封装RPC,没有完全把HTTP当成应用层协议,而是把HTTP协议作为传输层协议,然后在HTTP之上建立自己的应用层协议。

3. 应用维度

第一次请求的时候对资源产生了副作用,但是以后的多次请求都不会再对资源产生副作用,这里的副作用指不会对结果产生破坏或者产生不可预料的结果。

产生幂等性场景

  • 网络波动,可能引起重复请求
  • 用户重复操作,用户在使用产品是可能会五一的出发多次下单多次交易,甚至没有响应而有意触发多笔交易。
  • 应用使用了失败或者超时机制(Nginx重试、RPC重试、业务层重试)。
  • 第三方平台的接口(支付成功问题接口)。
  • 中间件、应用服务根据自身特性,也可能进行重试。
  • 双击提交按钮
  • 页面重复刷新
  • 多核浏览器重复操作,导致重复提交表单
  • 浏览器重复的HTTP请求
  • 定时任务多次执行

幂等性在哪一层实现

分布式微服务在哪一层解决幂等性问题?

  • Nignx、网关不适合做幂等性,因为不能在这写业务逻辑代码。
  • Service层,不需要做幂等性,最终对数据更改的是DAO层,所以Service一般不做幂等性。
  • DAO层需要做幂等性分析,因为直接对接数据,可能会产生不可预测的副作用。

数据访问层的幂等性

写请求、读请求?

读请求不会产生副作用。不改变数据的操作不需要做幂等。

写请求因为修改数据,需要做幂等。

insert操作

对于Insert操作,分为两种情况:

自增主键

多次Insert后会产生数据相同,但是主键不相同的数据。

业务主键

第二次Insert时,会因为主键冲突而报错。

delete操作

对于Delete操作,分为两种情况:

相对值删除

比如删除 top 数据,多次操作会导致幂等问题。

绝对值删除

通过Id删除,只会删除一个数据。

update操作

相对值更新

update product_info set prince = price + 99 where id = 1234 ;

无法保证幂等性

绝对值更新

update product_info set prince = 99 where id = 1234 ;

可以保证幂等性

所以对数据写的时候考虑幂等性。幂等性还分为广义的幂等性和狭义的幂等性,单库属于狭义的幂等性,而如今分布式系统中,需要分布式事务保证广义的幂等性。

  • insert要求唯一业务主键
  • delete中相对删除不具有幂等性

4. 保证幂等性的方法

4.1. 前端幂等性实现(不可靠)

4.1.1. 按钮置灰

按钮只可操作一次,一般是提交完成后按钮置灰或者loading状态,这里使用一些js组件实现,消除用户因为重复点击而产生的副作用,比如添加操作,由于点击两次而产生的两条记录。

缺点:用户可能会绕过js验证,所以前端实现的幂等性只能防止小白。

4.1.2. Token机制

产品上允许重复提交,但要保证重复提交不产生副作用,进入页面时申请一个Token,后面的所有请求都带上这个Token,根据Token来避免重复请求。

4.1.3. Post / Redirect / Get 模式

在提交后执行页面重定向,就是所谓的Post-Redirect-Get模式。当用户提交表单时,重定向到一个成功界面,防止用户刷新导致的重定向提交,同时也不会出现浏览器表单重复提交的警告,也能消除浏览器前进和后退导致的同样出伏提交问题。

4.1.4. Session中存放特殊标志

在服务器端,生成一个唯一标识符,存入Session,同时将它写入表单的隐藏中,然后提交表单,服务端会判断session中的标识符和表单中的标识符是否一致,如果一致,则表示首次提交,并将标识符移除,否则是重复提交。

4.2. 后端幂等性实现

使用唯一索引防止幂等性问题

像上文中说过的insert业务主键,可以有效的保证幂等性。

4.2.1. Token + Redis 的幂等方案

申请Token+业务操作两个阶段,整个流程如下图所示,但是业务操作需要加分布式锁来处理。

4.2.2. 状态机幂等

对于更新操作,设定更新状态操作,结合CAS思想,假设订单状态有待支付、支付中、支付成功、支付失败、订单超时等,在SQL语句where中加上status = 期望的值然后进行修改,这样也只会修改一次。

4.2.3. 乐观锁实现

更新已有数据,进行加锁更新,设计表结构时使用乐观锁,通过version来做乐观锁,即可保证效率,又能保证幂等性。乐观锁的version版本在更新业务时是递增的。

4.2.4. 防重表实现幂等性

防重表类似于锁的机制,保证当前处理订单只有一个线程。但是对于处理完成后,此订单的第二次操作同样会带来副作用,这里就需要配合其他机制来保证了,比如状态机。

4.2.5. Select + Insert

此方案是解决单机的幂等性问题的,先查询在判断是否插入,但是并发的时候需要加锁处理。

4.2.6. 分布式锁

进入方法时,先去获取锁,如果获取锁了,进行业务操作,如果没获取,等待锁的释放。同时分布式锁还有很多的细节,这里先不说了。

常用解决分布式锁的工具有Redis、zookeeper。思路类似于防重表。

4.2.7. 缓冲队列

按照消息的顺序来保证幂等性,同步改为异步,高吞吐量,但是不能同步返回结果。

本文发布于:2024-01-28 01:09:19,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/17063753653749.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:接口   方案
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23