幂等一般指的是方法被多次重复执行的时候,所产生的影响和第一次执行的影响效果相同。之所以要考虑幂等性的问题是因为在网络通信里面存在两种行为可能会导致接口被重复调用:
- 用户的重要提交或者用户的恶幕攻击,导致这个请求会被多次重复执行
- 在分布式架构中为了避免网络通信导致数据丢失,在服务间进行通信的时候都会设计超时重试的机制,而这种机制有可能导至服务端接口被重复调用
所以在程序设计里面对于数据变更类的接口要保证接口的幂等性,而幂等性的核心思想就是保证这个接口的执行结果只影响一次后续即使再次调用也不能对数据产生影响,所以基于这个诉求,常见的方法有很多:
- 使用数据库的唯一约束实现幂等,比如对于数据插入类的场景,比如创建订单,因为订单号肯定是唯一的,所以如果是多次调用就会触发数据库的唯一约束异常从而避免一个请求创建多个订单的问题。
- 使用redis里面提供的setNX指令,比如对于MQ消费的场景,为了避免MQ重复消费导致数据多次被修改的问题,可以在接受到MQ的消息时,把这个消息通过setNx写入到redis里面,一旦这个消息被消费过,就不会再次消费。
- 使用状态机来实现幂等,所谓的状态机是指一条数据的完整运行状态的转换流程,比如订单状态,因为它的状态只会向前变更,所以多次修改同一条数据的时候,一旦状态发生变更,那么对这条数据修改造成的影响只会发生一次。
但是不管什么样的方法无非就是两种:
- 要么就是接口只允许调用一次,比如唯一约束,基于redis锁
- 要么就是对数据的影响只会触发一次,比如状态机、乐观锁