在日常系统设计过程中或者在架构设计评审会上,经常会听到这个服务需要注意幂等性,但到底什么是幂等性,估计同学们可能都一知半解,那今天就来说一说幂等性究竟是什么,以及其作用是什么,怎么解决幂等性问题。
幂等,来源于数学中的一个概念,指用相同的参数重复执行函数,永远能获得相同结果的函数,即f(f(x)) = f(x)这个等式永远成立,映射到系统设计上则多次调用对系统的产生的影响或变化都是一样的。
幂等性强调的是外界通过接口对系统内部的影响, 一次或多次调用对某一个资源应该具有同样的副作用就行。
==========================================================
幂等性的场景有哪些?
1)分布式架构中,若出现服务调用超时的现象,可能会进行重试;
2)用户交互过程中多次点击,触发多次调用;
3)异步回调模式中,因异常情况会导致多次回调;
幂等性的作用是什么?
保证多次调用对资源的影响是一致的,我们利用资源处理应用来说明一下
HTTP方法与数据库操作的映射关系:
HTTP方法 | 数据库操作 |
PUT | CREATE |
GET | READ |
POST | UPDATE |
DELETE | DELETE |
通常只需要对写请求作幂等性处理
查询
SELECT * FROM users WHERE user_id;
不会对数据产生任何变化,天然具备幂等性。
新增
INSERT INTO users (user_id, name) VALUES (1, 'xxx');
case1:user_id若全局唯一,重复插入会失败,具有幂等性;
case2:user_id若非全局唯一,重复插入会成功,不具有幂等性;
修改
UPDATE users SET score = 30 WHERE user_id = 1;
case1:直接赋值,不管执行多少次score都一样,具备幂等性。
UPDATE users SET score = score + 30 WHERE user_id = 1;
case2:计算赋值,每次操作score数据都不一样,不具备幂等性。
删除
DELETE FROM users WHERE id = 1;
case1:绝对值删除,重复多次结果一样,具备幂等性。
DELETE top(3) FROM users;
case2:相对值删除,重复多次结果不一致,不具备幂等性。
幂等性问题如何来解决?
1)控制重复请求
控制动作触发源头,即前端做幂等性控制,仅算作辅助解决方案。
例如:
- 提交按钮仅可操作一次(提交动作后按钮置灰)
2)过滤重复动作
控制过滤重复动作,是指在动作流转过程中控制有效请求数量。
例如:
- 分布式锁,通过Redis控制同一时间只能完成一次请求;
- Token令牌,一个令牌只能允许放行一次请求
- 缓冲队列,将所有请求放入队列进行过滤处理;
3)解决重复写入
控制数据写入能力,即通过一些约束方式控制重复数据的写入。
例如:
- 悲观锁,即对数据库的行或表上锁,使其他并发执行发生排斥,达到锁的效果;
- 乐观锁,每次更新的时候带上version版本,如果version变化了,则更新失败;
- 唯一约束,利用了数据库的主键唯一约束的特性,来控制不会产生重复数据;
==========================================================
总结:幂等性处理虽然复杂了业务处理,也可能会降低服务的处理效率,但是有些业务场景为了保证系统数据的准确性,还是非常有必要的;
注:文章均原创,部分图片及文字来源于网络,若涉及版权,请联系作者,将第一时间备注出处,谢谢。