什么是幂等性
幂等性,一般分布环境下会遇到的常见问题,指多次操作所得到结果一样。
一般接口调用需要处理幂等性问题,有时候是需要防止幂等操作导致出现数据重复等问题,有时候需要保证幂等发生。
像我们的sql操作中:
insert : insert每次都会新增一条数据,是非幂等操作。
update : update 更新同一个值时,结果都一样,是幂等操作。
delete : 删除同一条数据结果都一样,是幂等操作。
select : 查询同一条数据结果都一样,是幂等操作。
这些sql操作关联到相应接口中,就会出现各种幂等问题。
比如我们知道,浏览器与后端服务是通过http(https)请求进行交互,而http请求的底层是通过tcp封装的,tcp有超时重试机制,在http协议封装时,对于因为网络抖动或者其他问题导致的超时确认数据或者丢失数据,会进行重发,这时候就产生了幂等操作。如果我们没有做一些幂等处理,就很容易产生重复数据或者相同调用结果,针对这种情况,我们需要保证结果幂等,所以就不能因为网络抖动重复请求而产生两条数据。
还有一种情况针对于我们接口管理平台所引发的接口重复消费,或者mq消息队列的消息重复消费,都会产生幂等问题。
……
保证幂等性与防止幂等性
对于类似因为网络抖动或者其他原因而产生的重复请求,我们应该保证其结果幂等,也就是说不能同一条数据产生多种结果。
对于这种问题的处理,常见的方案有:
乐观锁方案
比如update类型的接口操作,那我们在设计数据库表的时候就可以设计一个version字段,作为乐观锁,每次进行update时比对其版本,如果版本不一致,说明该请求已过期,不让其成功。
还可以通过时间戳实现乐观锁,进行幂等校验。
统一id方案(redis)
还有在分布式环境下我们可以获取统一的id(通过redis来实现),在消费完成后,该id移除,来保证其幂等性,也就是保证消息或者接口不重复消费。
使用唯一id来保证幂等(下游传递或者数据库表主键)
区分redis实现的统一id,这个id类似表主键id,通过其来保证结果幂等性,也就是不会产生重复数据。
使用token来保证幂等
可以防止前端页面重复提交等问题,参考如下示意图: