分布式幂等性方案

  1. insert 前先 select

在保存数据的接口中,在insert前,先根据requestId等字段先select一下数据。如果该数据已存在,则直接返回,如果不存在,才执行  insert操作。

  1. 加唯一索引

加唯一索引是个非常简单但很有效的办法,如果重复插入数据的话,就会抛出异常,为了保证幂等性,一般需要捕获这个异常。

如果是java程序需要捕获:DuplicateKeyException异常,如果使用了spring框架还需要捕获:MySQLIntegrityConstraintViolationException异常。

  1. 加悲观锁

更新逻辑,比如更新用户账户余额,可以加悲观锁,把对应用户的哪一行数据锁住。同一时刻只允许一个请求获得锁,其他请求则等待。

select * from user id=123 for update;

这种方式有一个缺点,获取不到锁的请求一般只能报失败,比较难保证接口返回相同值。

  1. 加乐观锁

更新逻辑,也可以用乐观锁,性能更好。可以在表中增加一个timestamp或者version字段,例如version:

在更新前,先查询一下数据,将 version 也作为更新的条件,同时也更新 version:

update user set amount=amount+100,version=version+1 where id=123 and version=1;

更新成功后,version 增加,重复更新请求进来就无法更新了。

  1. 建防重表

有时候表中并非所有的场景都不允许产生重复的数据,只有某些特定场景才不允许。这时候,就可以使用防重表的方式。

例如消息消费中,创建防重表,存储消息的唯一 ID,消费时先去查询是否已经消费,已经消费直接返回成功。

  1. 状态机

有些业务表是有状态的,比如订单表中有:1-下单、2-已支付、3-完成、4-撤销等状态,可以通过限制状态的流动来完成幂等。

  1. 分布式锁

直接在数据库上加锁的做法性能不够友好,可以使用分布式锁的方式,目前最流行的分布式锁实现是通过 Redis,具体实现一般都是使用 Redission 框架。

  1. token 机制

请求接口之前,需要先获取一个唯一的 token,再带着这个 token 去完成业务操作,服务端根据这个 token 是否存在,来判断是否是重复的请求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值