引入了幂等性,即同一个操作执行多次,效果是一样的。比如http的get请求和数据库的select请求都是幂等的。在分布式系统中,保证接口的幂等性非常重要。比如提交订单、扣款等接口必须保证幂等性,否则会造成重复创建订单、重复扣款,那么如何保证接口的幂等性呢?保证幂等性的前端方法只能点击一次。用户点击按钮后,按钮会变灰,或者显示加载状态的RPG模式为Post-Redirect-Get。客户提交表单后,执行客户端重定向,进入提交成功页面。避免用户按F5刷新导致的重复提交,也可以消除按浏览器返回键导致的重复提交。目前,大多数公司都是这样做的。比如淘宝、京东等后端保证幂等性的方法就是使用唯一索引,为业务的唯一字段添加唯一索引,这样当数据重复时,插入数据库会抛出异常状态机IdempotentIf业务需要修改订单状态,例如订单状态为待支付、支付中、支付成功、支付失败。设计时最好只支持状态的单向变化。这样更新的时候可以加上条件,多次调用只会执行一次。比如要更新订单状态支持成功,之前的状态必须在paymentupdatetable_namesetstatus=paymentsuccesswherestatus=optimisticlockinpayment实现幂等查询数据获取版本号,通过版本号更新。如果版本号匹配,则更新版本号。不匹配则不更新--如果查询版本为1--如果查询版本为1selectversionfromtable_namewhereuserid=10;--添加10updatetable_namesetmoney=money-10,version=version+1whereuserid=10andversion=1用户的帐户。乐观锁是通过条件来实现的,比如库存不能超卖,数量不能小于0等订单进行一系列操作的时候,可以在防重表中插入一条记录。如果插入成功,将进行后续操作。如果插入失败,则不会进行后续操作。本质上可以看成是基于MySQL的分布式锁。根据业务场景判断执行成功后是否删除防重表中对应的数据。在实现幂等执行方式时,首先根据业务的唯一id获取分布式锁。获取成功则执行,失败则不执行。基于redis、zookeeper、mysql可以实现分布式锁。分布式锁的细节就不介绍了。select+insert首先检查是否有符合要求的数据,如果没有则进行插入。在没有并发的系统中,可以保证幂等性。高并发下不要使用这种方式,同样会造成重复插入数据。我一般做messages幂等的时候都是先select,直接返回数据。如果没有数据,则加分布式锁执行插入操作。全球唯一编号实现幂等性。使用source(来源)+seq(序号)判断请求是否重复,repeat则直接返回请求重复提交,否则执行。比如有多个第三方系统调用服务时,可以使用这种方式。转载本文请联系Java石塘公众号。
