Java接口幂等性,如何重试?

Java接口幂等性,如何重试?


文章目录

  • Java接口幂等性,如何重试?
  • 前言
  • 一、幂等性是什么?
  • 二、为什么要幂等性?
  • 三、使用什么办法实现幂等性?
    • 1.insert前先select
    • 2.加悲观锁
    • 3.加乐观锁
    • 4.加唯一索引
    • 5.Redis加分布式锁
    • 6.获取token
  • 总结


前言

当我们写好一个项目时,有没有深深的思考过,如何处理接口幂等性问题呢?今天我们以屈原这句著名诗句“路漫漫其修远兮,吾将上下而求索”的精神来探索一下这个问题。


一、幂等性是什么?

幂等性:简单来说就是一个操作多次执行的结果和一次执行产生的结果一致。

二、为什么要幂等性?

答:在计算机应用中,可能造成网络抖动、临时故障、或者服务调用失败,尤其是分布式系统中,接口调用失败更为常见。为了保证服务的完整性,我们可能会发起接口的重试调用,如果接口不处理幂等,可能会对系统造成很大的影响,因此接口的幂等设计尤其重要。

如在支付中,如果没有幂等性,接口的重试可能造成重复支付。

幂等性和防重是不一样的,防重不考虑返回值,幂等性要求返回值一样。
Java接口幂等性,如何重试?_第1张图片

三、使用什么办法实现幂等性?

1.insert前先select

通常情况下,在保存数据的接口中,我们为了防止产生重复数据,一般会在insert前,先根据namecode字段select一下数据。如果该数据已存在,则执行update操作,如果不存在,才执行 insert操作。

缺点: 该方案可能是我们平时在防止产生重复数据时,使用最多的方案。但是该方案不适用于并发场景,在并发场景中,要配合其他方案一起使用,否则同样会产生重复数据。我在这里提一下,是为了避免大家踩坑。

2.加悲观锁

为了解决这个问题,可以加悲观锁,将用户A的那行数据锁住,在同一时刻只允许一个请求获得锁,更新数据,其他的请求则等待。

缺点:不适合幂等性设计场景,但是在防重场景中是可以的使用的。

3.加乐观锁

为了提升接口性能,我们可以使用乐观锁。需要在表中增加一个timestamp或者version字段。

Java接口幂等性,如何重试?_第2张图片

4.加唯一索引

绝大数情况下,为了防止重复数据的产生,我们都会在表中加唯一索引,这是一个非常简单,并且有效的方案。
加了唯一索引之后,第一次请求数据可以插入成功。但后面的相同请求,插入数据时会报Duplicate entry '002' for key 'order.un_code异常,表示唯一索引有冲突。虽说抛异常对数据来说没有影响,不会造成错误数据。但是为了保证接口幂等性,我们需要对该异常进行捕获,然后返回成功。

5.Redis加分布式锁

其实前面介绍过的加唯一索引或者加防重表,本质是使用了数据库分布式锁,也属于分布式锁的一种。但由于数据库分布式锁的性能不太好,我们可以改用:rediszookeeper

redis分布式锁的实现方式有三种:

1、setNx命令

2、set命令

3、Redission框架

具体步骤:

1、用户通过浏览器发送请求,服务器会收集数据,并且生成订单号code作为唯一业务字段。

2、使用redis的set命令,将该订单code设置到redis中,同时设置超时时间。

3、判断是否设置成功,如果设置成功,说明是第一次请求,则数据进行操作。

4、如果设置失败,说明是重复请求,则直接返回成功。
Java接口幂等性,如何重试?_第3张图片

6.获取token

除了上述方案之外,还有最后一种使用token的方案。该方案跟之前的所有方案都有点不一样,需要两次请求才能完成一次业务操作。

两次请求:

1. 第一次请求获取`token`
2. 第二次请求带着这个`token`,完成业务操作。

具体步骤:

  1. 用户访问页面时,浏览器自动发起获取token请求。
  2. 服务端生成token,保存到redis中,然后返回给浏览器。
  3. 用户通过浏览器发起请求时,携带该token。
  4. 在redis中查询该token是否存在,如果不存在,说明是第一次请求,做则后续的数据操作。
  5. 如果存在,说明是重复请求,则直接返回成功。
  6. 在redis中token会在过期时间之后,被自动删除。

总结

以上就是今天要讲的内容,本文仅仅简单介绍了使用什么办法实现幂等性,而具体的解决方案还是需要根据项目自身选择。

你可能感兴趣的:(java,安全性测试,分布式,redis)