当前位置: 首页 > Web前端 > HTML

如何保证接口的幂等性?

时间:2023-03-28 01:36:08 HTML

什么是接口幂等性?先看幂等性的概念:幂等性本来是一个数学概念,可以理解为:同一个接口,同一个请求多次发出,必须保证操作只执行一次。当调用接口出现异常,反复尝试总会造成系统无法承受的损失,所以必须杜绝这种现象的发生。例如,在以下几种情况下,如果不实现接口的幂等性,将会产生严重的后果:在支付接口中,重复支付会导致多次扣款;在订单界面,同一个订单可能会创建多次。为什么会出现接口幂等性问题?那么,在什么情况下会出现接口幂等性的问题呢?网络波动可能会导致用户重复请求执行重复操作。用户在操作过程中可能会无意中触发多笔订单交易,甚至有意触发多笔交易而无响应。应用使用失败或超时重试机制(Nginx重试、RPC重试或业务层重试等)页面反复刷新。使用浏览器后退按钮重复之前的操作,导致表单重复提交。使用浏览器历史记录重复提交表单。浏览器重复HTTP请求。定时任务重复执行。接口幂等性?那么最重要的是,如何保证接口的幂等性呢?解决方案分为两个方向,一是在client端防止重复调用,二是在server端进行校验。当然,客户端防止重复提交也不是绝对可靠的。优点是实现起来比较简单。该按钮只能操作一次。一般提交后按钮会变灰或loding,以消除用户重复点击产生的重复记录,比如添加操作。两次点击生成两条记录。token机制功能允许重复提交,但是需要保证重复提交不会产生副作用,比如点击n次只生成一条记录。具体实现是在进入页面的时候申请一个token,之后所有的请求都携带这个token,后端根据这个token避免重复请求。使用Post/Redirect/Get方式在提交后进行页面重定向。这就是所谓的Post-Redirect-Get(PRG)模式。简单地说,当用户提交表单时,它会跳转到一个重定向的信息页面。这样就避免了用户按F5刷新导致的重复提交,也不会出现浏览器表单重复提交的警告,同样可以解决按浏览器前进后退导致的重复提交问题被淘汰。在服务器端的session中存储特殊的flags,生成一个唯一的标识符,存储在session中,同时前端获取这个标识符的值写入到隐藏的form中,供用户使用输入信息并点击一起提交。在服务器端,获取表单中隐藏字段的值,并将其与会话中的唯一标识符进行比较。如果相等,说明是第一次提交,然后处理这个请求,然后去掉session中的唯一标识。如果不相等,说明是重复提交。,不做进一步处理。Useauniqueindextopreventnewdirtydata利用数据库的唯一索引机制。当数据重复时,插入数据库时??会抛出异常,保证不会出现脏数据。更新已有数据可以使用乐观锁来更新已有数据,或者在设计表结构时使用乐观锁,使用版本做乐观锁,既可以保证执行效率,又可以保证幂等性。乐观锁的version版本在更新业务数据,updatetablesetversion=version+1whereid=#{id}andversion=#{version}例子:当有重复请求时,第一个请求会拿到version当前产品的编号,获取到的版本为1,然后因为第一次请求还没有更新产品的版本,所以第二次请求获取到的版本还是1,此时带上版本作为条件,第一次请求操作更新时自增update,此时商品的版本会变成2。第二次请求操作更新时,很明显版本不一致导致更新失败。select+insertorupdateordelete这种方案是在操作前查询,满足要求后插入。该方案可以解决没有并发的系统中的幂等问题。当单个JVM有并发时,可以使用JVM锁来保证幂等性。平等,幂等性在分布式环境下是无法保证的,可以用分布式来保证。分布式锁如果是分布式系统,很难建立全局唯一索引。例如,无法确定唯一字段。这时候可以引入分布式锁向业务系统或者通过第三方系统(redis或者zookeeper)插入数据。更新数据,获取分布式锁,执行操作,然后释放锁。要点:长流程要求不能并发执行。可以根据一定的flag(用户ID+后缀等)获取分布式锁,一个可以执行成功,执行完成后释放分布式锁(分布式锁必须由第三方提供系统)。状态机幂等性在设计文档相关的业务或者任务相关的业务时,肯定会涉及到状态机(状态变化图),即业务文档上有一个状态,在不同的情况下状态会发生变化。下一个状态有一个有限状态机。这时候,如果状态机已经处于下一个状态,此时对前一个状态有一个改变,理论上是无法改变的。在这种情况下,有限状态机的幂等性得到了保证。注:订单等单证类业务状态流转时间长。需要对状态机有深刻的理解,这对提高业务系统设计能力有很大的帮助。防重表以支付为例:使用唯一主键作为防重表唯一索引,例如使用订单号作为防重表唯一索引,每次请求插入一个一条数据按照订单号放入防重表,插入成功说明可以处理后面的业务。业务逻辑处理完成后,删除防重表中的订单号数据。如果后面有重复请求,会因为防重表的唯一索引导致插入失败,直接返回操作失败,直到第一次根据第二次请求返回的结果,可以看出函数防重表是加锁的功能。注意:最好结合状态机的幂等性,先判断缓冲队列,快速接收请求放入缓冲队列,然后使用异步任务处理队列中的数据,过滤掉重复的请求。该方案的优点是将同步处理改为异步处理,吞吐量高。缺点是不能及时返回请求结果,需要后续轮询获取处理结果。比如通过source源+唯一序列号将全局唯一编号传给后端,后端判断是否重复请求。并发时只能处理一个请求。其他相同的并发请求要么返回请求重复,要么等待上一个请求执行完成。再次执行。作者:程序员大斌链接:https://juejin.cn/post/718422...来源:稀土掘金版权归作者所有。商业转载请联系作者授权,非商业转载请注明出处。