理解接口幂等性:构建可靠的API

30 阅读4分钟

为什么需要幂等性呢?

  在我们日常业务开发中,经常会遇到重复提交的情况,无论是由于网络问题无法收到请求结果而导致的重新发起请求,或者是前端操作抖动而造成重复提交情况。在上述场景下,需要保证用户操作的幂等性。否则将可能导致如:重复下单、重复发货、库存重复扣减、重复支付等问题出现。

什么是幂等性

  函数/接口幂等性是一种重要的概念,或者说是一种机制,它可以确保同一个请求多次执行时,不会影响系统状态,也不会对系统造成改变。

常见的幂等设计方案

  那么对于接口的幂等性应该怎么设计呢?接口幂等性应遵循以下几点:

  • 使用唯一标识符

  为每个请求生成一个唯一的标识符,并将其包含在请求中。服务器端可以使用这个标识符来检测重复请求。

  • 幂等性校验

  在处理请求之前,服务端需要检查该请求的唯一标识符是否已经处理过。

  • 幂等性保证

  如果服务端检测到请求已经处理过,可以直接返回之前的结果或给出友好提示,而不进行重复处理。

数据库实现

  • 唯一索引

  在保存数据的时候,为了防止多次执行造成数据库数据重复,我们可以在数据库中通过设置关键数据字段(关键数据由实际的业务决定,比如说用户信息中的电话号码,身份证号等)的唯一性索引来实现幂等。使用唯一索引可以避免脏数据的添加,当插入重复数据时数据库会抛异常。

  • 悲观锁

  在获取数据时进行加锁,当同时有多个重复请求时,只有一个能执行,其他请求都无法进行操作。

  • 乐观锁

  为数据字段增加一个version字段,当数据需要更新时,先去数据库里获取此时的version版本号,更新数据时首先和版本号作对比,如果不相等说明已经有其他的请求去更新数据了,提示更新失败。

  如果我们项目使用的是Spring Data JPA持久化框架,实现乐观锁十分简单,@Version是jpa里提供的一个注解,其作用是用于实现乐观锁,只需将我们的一个java的entity加上一个由@version修饰的字段即可。

image.png

Redis+Token实现

  用户在进入操作页面时,先向服务端请求一个Token(服务端生成Token同时将其存放到Redis中),当用户提交请求时,将Token存放到Headers中,服务端检查Redis中Token是否存在,如果Token存在,就执行删除命令,然后正常执行后面的业务逻辑。如果不存在对应的Token就返回重复执行的错误信息,来保证幂等。

image.png

状态机

  对于一些具有明确状态转换的操作,可以通过状态机来实现幂等性。状态机定义了系统在不同状态下允许执行的操作以及操作对状态的影响。当接收到一个操作请求时,系统首先根据当前的状态判断该操作是否合法。如果合法,执行操作并更新系统状态;如果不合法(例如,在某个状态下不允许执行该操作或者该操作已经被执行过),则直接返回相应的错误信息或忽略该请求。

总结

  幂等性作为一个重要的系统特性,我们可以在不同的场景中实现幂等性,有效地避免重复操作带来的各种问题。然而,我们需要在开发过程中充分考虑其他因素(业务逻辑复杂性增加和分布式环境下的一致性问题等),并采取相应的应对策略,以确保幂等性的有效实现。