幂等
对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次调用而产生脏数据。
幂等场景
如下场景中可能会发生重复请求:
- 网络波动:网络波动可能会引发对端重试机制。
- 消息消费:网络延迟、消费者异常、消费者延迟消费,会造成MQ重试补偿,在重试过程中,可能会造成重复消费。
- 用户重复操作:用户在使用产品时,可能无意识进行了多次触发,或因为没有响应而有意进行多次触发。
- 重试机制:如nginx重试,RPC框架的重试机制等。
CURD中的幂等
- 新增类的操作:不具备幂等,可能会重复插入多条数据。
- 查询类操作:重复查询不会产生或变更数据,查询操作具有天然幂等性。
- 更新类操作:
- 计算式update:不具备幂等性
例:update goods set number=nember-1 where id=1 - 非计算式:具备幂等条件
例:update goods set number=newNumber where id=1
删除类操作: - delete操作具备幂等性。
- 业务中的逻辑删除也具备幂等性。
- 计算式update:不具备幂等性
幂等的重要性
- 电商超卖
- 重复转账、扣款、支付
- 重复增减积分、发放优惠券等
解决方案
- 使用全局唯一的ID
根据业务的操作和内容生成一个全局唯一的ID,在执行操作之前根据全局ID是否存在来判断操作是否执行。全局唯一ID可以持久化到数据库中。
使用全局唯一ID是一个通用方案,可以支持插入、更新、删除业务操作。 - 去重表
适用于业务中有唯一标识的插入场景,比如在支付场景中,如果一个订单只能支付一次,订单的ID就可以作为唯一ID。建立一张去重表,并且将唯一标识作为唯一索引,在实现时,先把支付单据写入去重表,把支付场景放在一个事务中,如果重复创建,数据库会抛出唯一约束异常,操作会回滚。 - 插入或更新
适用于新增数据并且有唯一索引的情况,这时使用InsertOrUpdate操作,唯一索引不存在时插入数据,存在时则更新数据。
网友评论