实现幂等性的几种方式及其注意事项

幂等性是系统设计中的重要概念,确保用户多次操作同一资源时结果不变。在分布式环境下,尤其需要考虑幂等性以防止重复提交等问题。本文介绍了几种实现幂等性的方法,如数据库唯一索引、防重表、行锁事务、版本号字段、状态字段判断以及分布式锁(如Redis或Zookeeper)。这些方法有助于构建更健壮、可靠的系统,避免因网络延迟或用户误操作导致的异常状态。
摘要由CSDN通过智能技术生成
什么是幂等性?

幂等性就是当用户对于同一操作发起一次或多次请求时,得到的结果都是一样的。比如购物下单时,即使用户可能由于手机卡顿等原因点了好几次“提交订单”,那也只能扣一次费和生成一个订单。

什么情况下需要做幂等性处理?

读取和删除,操作一次和多次的结果都是一样的,所以不用考虑幂等处理。下面两种情况需要考虑:
(1)insert,多次请求时可能会产生重复数据
(2)update,分情况,如果像 update order set status=2 where id=1这种,不用考虑。像update order set status=status+1 where id=1就需要考虑了。

实现幂等性的方式

下面列举一下在分布式情景下实现幂等性的几种方式。

1、给数据库中的某个字段设置唯一索引

比如订单表,给订单id设置唯一索引,如果库中已经有此订单了,就会insert失败。

使用时需要注意:这个接口可能会报重复键异常,所以我们应做个捕获异常的处理。如果捕获到DuplicateKeyException和MySQLIntegrityConstraintViolationException异常后,依旧返回请求成功。

2、给数据库的某两个字段设置联合唯一索引

这条是1的延伸。有些库不是物理删除,而是逻辑删除,还有一个is_delete字段(是否删除:0否、1是)。
那就可以将订单id和is_delete字段设置个联合唯一索引。

3、新建个防重表

不搞订单表,而是新建个防重表,表里有id和订单id两个字段,然后给orderId建个唯一索引。

使用时需要注意:防重表需要和订单表在同一个数据库且逻辑代码需要在同一个事务中。

4、行锁+事务——悲观锁

使用for update,for update的作用就是对这条数据加行锁,等本事务执行完才会释放锁。在此期间,其它事务可以任意读,如果想修改的话得排队。

第一步:

select * from order where id=1 for update;

第二步:
处理业务代码,对这条数据进行修改。两步需要在同一个事务里。

使用时需要注意:
(1)需要选择mysql默认的InnoDB搜索引擎,因为MyIsam不支持事务。
(2)查询条件要带主键,要不然会锁表

5、新增版本号字段——乐观锁

在数据库里加个version字段,如果想修改数据,先select再update,当update时判断条件中需要有version

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

6、根据状态字段来判断

比如订单表的订单状态分为几种,status:0下单未支付、1已支付、2订单完成、3订单取消。update的判断条件加个status:

update order set status=1 where order_id=1 and status=0

7、分布式锁

可以使用redis或zk做分布式锁,其中redis分布锁的实现方式有3种:
(1)setNx
(2)set
(3)Redission

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卡夫卡的熊kfk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值