本文已收录到Github仓库,里面包含计算机基础、Java基础、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模式、架构、校招机构Recruit以及分享核心知识点,欢迎star~Github地址大家好,我是大斌~今天来聊聊接口幂等性。什么是接口幂等性?如何保证接口的幂等性?什么是接口幂等性?先看幂等性的概念:幂等性本来是一个数学概念,可以理解为:同一个接口,同一个请求多次发出,必须保证操作只执行一次。当调用接口出现异常,反复尝试总会造成系统无法承受的损失,所以必须杜绝这种现象的发生。例如,在以下几种情况下,如果不实现接口的幂等性,将会产生严重的后果:在支付接口中,重复支付会导致多次扣款;在订单界面,同一个订单可能会创建多次。为什么会出现接口幂等性问题?那么,在什么情况下会出现接口幂等性的问题呢?网络波动可能会导致用户重复请求执行重复操作。用户在操作过程中可能会无意中触发多笔订单交易,甚至有意触发多笔交易而无响应。应用使用失败或超时重试机制(Nginx重试、RPC重试或业务层重试等)页面反复刷新。使用浏览器的后退按钮重复之前的操作,导致表单重复提交。使用浏览器历史记录重复提交表单。浏览器重复HTTP请求。定时任务重复执行。如何保证接口的幂等性?那么最重要的是,如何保证接口的幂等性呢?解决方案分为两个方向,一是在client端防止重复调用,二是在server端进行校验。当然,客户端防止重复提交也不是绝对可靠的。优点是实现起来比较简单。该按钮只能操作一次。一般提交后按钮会变灰或loding,以消除用户重复点击产生的重复记录。例如,加法操作会因为两次点击而产生两条记录。token机制功能允许重复提交,但必须保证重复提交不会产生副作用。比如点击n次只生成一条记录。具体实现是在进入页面的时候申请一个token,之后所有的请求都会携带这个token。后端根据token避免重复请求。Useauniqueindextopreventnewdirtydata利用数据库的唯一索引机制。当数据重复时,插入数据库时??会抛出异常,保证不会出现脏数据。更新已有数据可以使用乐观锁来更新已有数据,或者在设计表结构时使用乐观锁,使用版本做乐观锁,既可以保证执行效率,又可以保证幂等性。乐观锁的version版本在Updatingbusinessdata应该是自增的。updatetablesetversion=version+1whereid=#{id}andversion=#{version}例子:当有重复请求时,第一个请求会获取当前产品的版本号,获取到的版本为1,紧接着,由于第一次请求还没有更新商品的版本,第二次请求得到的版本还是1,此时第一次请求操作更新时,带上版本作为条件,自增更新。此时产品的版本会变成2,当第二次请求操作更新时,很明显版本不一致导致更新失败。select+insertorupdateordelete这种方案是在操作前查询,满足要求后插入。该方案可以解决没有并发的系统中的幂等问题。当单个JVM有并发时,可以使用JVM锁来保证幂等性。平等,幂等性在分布式环境下是无法保证的,可以用分布式来保证。分布式锁如果是分布式系统,很难建立全局唯一索引。例如,无法确定唯一字段。这时候可以引入分布式锁向业务系统或者通过第三方系统(redis或者zookeeper)插入数据。更新数据,获取分布式锁,执行操作,然后释放锁。要点:长流程要求不能并发执行。可以根据一定的flag(用户ID+后缀等)获取分布式锁,一个可以执行成功,执行完成后释放分布式锁(分布式锁必须由第三方提供系统)。状态机幂等性在设计文档相关的业务或者任务相关的业务时,肯定会涉及到状态机(状态变化图),即业务文档上有一个状态,在不同的情况下状态会发生变化。下一个状态有一个有限状态机。这时候,如果状态机已经处于下一个状态,此时对前一个状态有一个改变,理论上是无法改变的。在这种情况下,有限状态机的幂等性得到了保证。注:订单等单证类业务状态流转时间长。需要对状态机有深刻的理解,这对提高业务系统设计能力有很大的帮助。防重表以支付为例:使用唯一主键作为防重表唯一索引,例如使用订单号作为防重表唯一索引,每次请求插入一个一条数据按照订单号放入防重表,插入成功说明可以处理后面的业务。业务逻辑处理完成后,删除防重表中的订单号数据。如果后面有重复请求,会因为防重表的唯一索引导致插入失败,直接返回操作失败,直到第一次根据第二次请求返回的结果,可以看出函数防重表是加锁的功能。注意:最好结合状态机的幂等性,先判断缓冲队列,快速接收请求放入缓冲队列,然后使用异步任务处理队列中的数据,过滤掉重复的请求。该方案的优点是将同步处理改为异步处理,吞吐量高。缺点是不能及时返回请求结果,需要后续轮询获取处理结果。最后给大家分享一个Github仓库,里面有大斌编译的300多本经典计算机书籍PDF,包括C语言、C++、Java、Python、前端、数据库、操作系统、计算机网络、数据结构还有算法,机器学习,编程生活等等,可以star一下,下次找书直接上搜,仓库持续更新~Github地址
