• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

什么是幂等性解决

武飞扬头像
lovoo
帮助1

一、什么是幂等性:

就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。

在增删改查4个操作中,尤为注意就是增加或者修改,查询对于结果是不会有改变的,删除只会进行一次,用户多次点击产生的结果一样,修改在大多场景下结果一样,增加在重复提交的场景下会出现。

二、产生幂等性的场景

  • 幂等性问题在我们开发中,分布式、微服务架构中是随处可见的,因网络波动就可能重复请求。
  • 用户重复操作,用户在使用产品的时候可能无意多次点击,或者没有响应而导致多次下单或者交易。
  • 应用了超时或者失败重试机制。
  • 第三方平台的接口,因为异常导致多次异步回调。
  • 中间件、应用服务根据自身特性,也有可能进行重试。
  • 用户双击提交按钮。 页面重复刷新
  • 使用浏览器后退按钮重复之前的操作,导致重复提交表单。等等。

如:

1、向支付宝发起支付请求,由于网络问题或系统BUG重发,支付宝应该只扣一次钱。
2、用户在APP上连续点击了多次提交订单,后台应该只产生一个订单;

三、 解决幂等性的方案有:

1、唯一索引,防止新增脏数据。
2、利用 token 机制,防止页面重复提交。
3.、悲观锁(并发高的话慎用)
4.、乐观锁 (可能循环时间长开销大) Lock(单机环境适用)/数据库乐观锁
5、分布式锁(适用分布式系统)

1、建立唯一索引,防止新增脏数据。

可限制重复插入数据,当重复时,数据库会抛异常,保证不会出现脏数据。但体验不好,并且实用场景有限制。

使用全局唯一ID,就是根据业务的操作(业务类型)和内容生成一个全局ID,在执行操作前先根据这个全局唯一ID是否存在,来判断这个操作是否已经执行。如果不存在则把全局ID,存储到存储系统中,比如数据库、redis等。如果存在则表示该方法已经执行,这个全局ID有时效性。

2、 利用 token 机制,防止页面重复提交。

分为两个阶段,获取token和使用token。每次接口请求前先获取一个token,然后再下次请求的时候在请求的header体中加上这个token,后台进行验证,如果验证通过删除token,下次请求再次判断token是否相同,只有相同token的请求才能通过。

3、 使用悲观锁。

  • Java中悲观锁的代表是 synchronized 和 Lock 锁。
  • 数据可以在SQL语句后添加 for update进行锁定。

4、乐观锁 :

  • Java中了观锁的代表是 CAS 锁。
  • 数据库使用的是在表中添加一个version字段。

这种方法适合在更新的场景中,比如我们要更新商品的名字,这时我们就可以在更新的接口中增加一个版本号,来做幂等

取出的版本号是1
select id, name, version from goods where id = 1
更新是版本号也必须是1,如果版本号不等于1,则表示该数据被别的进程修改了
update goods  set  name=?, version=?  where id= 1  and  version = 1

5、Redision分布式锁 :

使用redission,只需要通过他的api中的lock和unlock即可完成分布式锁

String lockKey = "product001";
RLock lock = redisson.getLock(lockKey); 
try{
	// 解决过期时间内还未完成操作的问题
	lock.lock(30, TimeUnit.SECONDS); // 先拿锁,再设置超时时间
	// 4.真正操作商品库存
	synchronized (this){
	      int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("stock")); 
	      if (stock > 0){
	          int realStock = stock - 1;
	          stringRedisTemplate.opsForValue().set("stock", realStock   ""); // jedis.set(key, value);
	          System.out.println("扣减成功,剩余库存:"   realStock);
	      }else {
	          System.out.println("扣减失败,库存不足!");
	      }
	  }
}finally {
  lock.unlock(); // 释放锁
}
学新通

源代码下载:
https://gitee.com/charlinchenlin/koo-erp

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgfggek
系列文章
更多 icon
同类精品
更多 icon
继续加载