什么是幂等性?幂等性就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。举个简单例子,在用支付宝结账输完密码时突然网络异常,这时钱已经扣了(但我们看不到)。刷新一下界面,又回到了输入密码界面,这个时候如果再次输入密码,难道会扣两次钱吗?答:不会滴!这就是幂等性的意义,只要支付成功不论我输入几次扣款密码都不会再次扣款。
在以前的系统中,我们只需要将数据操作放入事务中即可,发生错误立即回滚,但是再响应客户端的时候也可能出现其他异常,但是不够保险。幂等性很好地解决了这个问题。
在我们常说的增删改查4种操作中,幂等性主要体现在增加和修改操作上。
查询的结果是不会变的;删除只会进行一次,用户多次点击的结果是一样的;修改在大多数场景下结果一样;增加(减少)在重复提交的场景下会出现。
接下来介绍几种常用接口幂等的方法。
方法一:加悲观锁(以支付系统为例)
1.接收到支付成功请求;
2.打开本地事物;
3.查询订单信息并加悲观锁;
4.判断订单是否处理;
5.若处理直接返回,若未处理,向下执行;
6.给本地系统用户加钱;
7.订单状态置为成功;
8.提交本地事物。
方法二:加乐观锁(以支付系统为例)
乐观锁和悲观锁处理步骤基本相似,在这里区分一下乐观锁和悲观锁。
乐观锁:
总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制和CAS算法实现。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库提供的类似于write_condition机制,其实都是提供的乐观锁。
悲观锁
总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。
方法三:唯一约束方式(以支付系统为例)
对于任何一个业务,有一个唯一的条件可以判断其是否处理
1.收到支付成功请求;
2.查询条件,判断订单是否处理;
3.如果处理了就返回,如果未处理继续向下执行;
4.打开本地事物;
5.给本地系统用户加钱;
6.订单状态设定为成功
7.提交本地事物。
这个唯一约束方式可以具体化,比如具体化一个门票(ticketID),有门票才能进行处理,没有门票就不能处理等等。
理论上乐观锁是最优的!
这个幂等性我也没有尝试过…只是在学习过程中产生了兴趣,了解了一下,如果有大佬发现其中的错误还请指正。