接口幂等性常见的解决方案【精华版】
一、什么是接口幂等性?
接口的幂等性是指:无论用户对某个操作发起一次请求还是多次请求,其结果应一致,且不会产生额外的副作用。
特性
- 多次调用结果一致:无论调用一次还是多次,返回结果和系统状态不变。
- 状态不可变:重复的请求不会对数据库、文件等资源产生重复修改。
- 与事务一致性相关:幂等性是分布式系统或事务一致性保障的重要组成部分。
示例场景
支付场景
用户购买商品并支付时,如果网络异常导致用户误以为支付失败而重复点击支付按钮,可能会导致多次扣款。实现接口幂等性可以避免这种问题。
二、什么情况下需要保证接口的幂等性?
-
前端重复提交
用户快速多次点击按钮,导致多次请求被提交。 -
消息重复消费
消息中间件(如 RabbitMQ)因网络问题重复投递消息,导致业务逻辑被多次处理。 -
页面回退再次提交
用户操作成功后返回页面并重复提交相同的数据。 -
微服务间调用
微服务调用因网络抖动或超时触发重试机制,可能引发重复请求。 -
关键业务场景
如支付、订单等重要操作,重复执行会导致严重后果。
三、数据库操作中的幂等性分析
1. 天然幂等操作
以下操作本身具备幂等性:
-- 查询操作(多次执行结果一致)
SELECT * FROM t_user WHERE id = 1;
-- 设置固定值(多次执行结果一致)
UPDATE t_user SET age = 18 WHERE id = 2;
-- 删除操作(数据被删除后结果不变)
DELETE FROM t_user WHERE id = 1;
-- 插入带唯一约束的记录(重复插入会报错)
INSERT INTO t_user (user_id, username) VALUES (1, '张三'); # userid 唯一主键
2. 非幂等操作
以下操作不具备幂等性:
-- 自增操作(多次执行结果不同)
UPDATE t_user SET age = age + 1 WHERE id = 1;
-- 插入未设置唯一约束的记录(多次插入会生成重复记录)
INSERT INTO t_user (user_id, username) VALUES (1, '张三'); # userid 不是主键 可以重复
在增删改查操作中的幂等性分析
在增删改查4个操作中,尤为注意就是增加或者修改,
A: 查询操作
SELECT * FROM user WHERE user_id = 1;
不管执行一次还是多次上面的查询语句,如果数据库记录没有变更的话,查询结果都是一样的。由此可见,SELECT 是天然的幂等操作。
B: 删除操作
DELETE FROM user WHERE user_id = 1;
不管是删除一次,还是删除多次,都是把数据删除,在不考虑返回结果的情况下,因此删除操作也是具有幂等性的。
C: 更新操作
幂等更新操作:
把表中 id 为 XXX 的记录的 A 字段值设置为固定值。这种操作不管执行多少次都是幂等的。
UPDATE user SET username = 'zhangsan' WHERE user_id = 1;
如上所示,将 username 字段改成一个固定的值,这种操作不管执行多少次,结果都是一样的,所以这种情况下更新操作是幂等的。
非幂等更新操作:
UPDATE user SET age = age + 1 WHERE user_id = 1;
这里将 age 字段进行递增操作,每执行一次,age 就会加一,显然每次执行结果都不一样,所以这种情况下更新操作就不是幂等的。
D: 新增操作
可能导致幂等性问题的新增操作:
在重复提交的场景下,可能会导致相同的订单被保存多份。例如用户下订单操作,如果网络卡顿,用户重复点击了多次购买按钮,那么就可能导致相同的订单被我们保存了多份。
INSERT INTO order(pkid, order_id, xx) VALUES (1, '20210304020226953568', ...);
假设 pkid 是自增,如果 order_id 没有做唯一约束的话,那么就可能导致同一个订单保存多条数据,不具备幂等性;如果 order_id 做了唯一约束,那么这个新增操作就是幂等的。

最低0.47元/天 解锁文章
665

被折叠的 条评论
为什么被折叠?



