软件开发中的幂等是什么

工作中经常会遇到一个事务型接口或者一个事务型方法被调用方重复调用,实际上每次调用的数据都是相同的,有可能是因为网络延迟,客户端点击了多次,也可能是调用方故意而为之,不论是哪种情况,我们都不能让这种重复的操作对我们自己的系统造成不必要的影响。因此,我们需要对于接口和方法做幂等校验。其实幂等过滤一直都贯穿IT行业,只不过现在随着互联网行业的发展,行业内的造词能力和词语引用能力越来越强,幂等被计算机行业正式引用。

幂等性

在数学概念里,幂等是指一次变换和N次变换的结果都相同。而在计算机概念中,幂等是指某一操作执行n次和执行一次所产生的影响是一样的,也就是重复执行这项操作也不会对系统造成改变,比如抢优惠券,每人限制抢一张优惠券,可以使用用户ID+优惠券ID做幂等条件,这样就可以保证每个用户只能抢一张此优惠券。

RESTFul幂等

  • GET请求:GET请求属于是非事务型请求,每次请求都不会对系统造成任何影响,所以这类接口本身就符合了幂等性(这里说的是对系统造成影响,而不是说每次调用获取到的数据相同,幂等是针对于系统而非接口)
  • DELETE请求:DELETE请求是一个特殊的事务型请求,在调用第一次的时候就已经把数据删除了,所以不论后续再次调用多少次,对系统产生的影响都是一样的,所以DELETE类型的请求本身也是符合幂等性的
  • PUT请求:PUT请求是对数据进行修改,理论上对同一URI进行多次PUT操作对整个系统的影响和一次PUT是相同的,但是这要结合接口具体代码实现来考量
    • 直接将PUT的数值替换掉原有数据:幂等
    • 每次调用都对某个数据递增:非幂等,需要手动幂等
  • POST请求:POST是创建资源的事务型请求,每次请求都会创建一份资源,所以多次调用对整个系统产生的影响是不同的,该类型的请求是非幂等的

常用幂等方法

  • 数据库唯一索引去重

    利用数据库唯一索引的特性达到幂等的效果,不会往数据表中插入两条幂等字段相同的数据。例如文章点赞功能,为了防止用户重复点赞,可以在点赞表中以用户ID+文章ID为唯一索引,这样就可以有效的防止用户给一篇文章重复点赞,最终达到幂等操作的效果。

  • 版本锁控制

    版本锁属于是乐观锁的一种实现,MySQL中的MVCC就是版本锁的一种应用方式,通过每次更新都通过版本号控制权限来达到幂等操作的效果

  • token缓存机制

    token缓存机制是一种比较常见的幂等处理方式,应用范围较广,不限定场景和语言。核心思想就是为每个请求分配一个全局唯一标识(token),一个token在一条业务线的每个阶段只能执行一次,执行之后将这个阶段的结果缓存起来,每次执行前先校验是否已有缓存,没有缓存则执行流程,已有缓存则直接返回结果。

总结

不同的业务需求会面临不同的幂等要求,也就会有不同的解决方案,所以幂等的实现难度是不同的。在做系统设计时,一定要将幂等性考虑周全,否则可能会给系统带来不必要的潜在隐患。

### 等性的定义和概念 #### 定义 等性(Idempotence)最初来源于数学领域,后来被引入到计算机科学中。它的核心特性在于,对于某个操作而言,无论执行多少次,只要输入条件一致,最终产生的结果都与第一次执行的结果完全相同[^1]。 #### 编程中的意义 在编程环境中,等操作意味着即使该操作被执行多次,也不会改变系统的状态或者数据的一致性。例如,在函数调用过程中,如果一个函数具有等性质,则不论此函数被调用了几次,其对外部环境的影响始终不变[^3]。 #### 接口设计中的应用 在现代软件开发尤其是RESTful API的设计中,等性扮演着至关重要的角色。具体来: - **GET、PUT 和 DELETE 请求**:这些方法通常被认为是天然具备等特性的。因为它们要么只读取资源(如 GET),要么修改现有资源而不依赖于之前的请求次数(如 PUT 或 DELETE)。因此不需要额外处理来实现等性。 - **POST 请求**:由于 POST 方法主要用于创建新资源,所以默认情况下并不保证等性。然而,在某些特定场景下,比如涉及设备配网、用户注册或设备注册等功能时,为了防止因网络延迟等原因造成的重复提交问题,往往需要通过特殊手段使 POST 请求也达到等的效果[^4]。 以下是关于如何确保 POST 请求等的一个简单例子: ```python class IdempotentPostHandler: def __init__(self, db): self.db = db def handle_post(self, request_id, data): if not self.db.exists(request_id): # 检查是否已存在相同的请求ID result = self.process_data(data) # 处理实际业务逻辑 self.db.save(request_id, result) # 将唯一标识符及其对应的数据保存至数据库 else: result = self.db.get(request_id) # 如果已经存在则直接返回之前存储的结果 return result ``` 上述代码片段展示了如何利用唯一的 `request_id` 来跟踪每一个 POST 请求的状态,从而保障整个过程满足等的要求。 --- ### §相关问题§ 1. 如何验证 RESTful API 中的某条路径是否真正实现了等? 2. 在分布式系统架构里,有哪些常见的策略可以用来增强接口的等能力? 3. 当遇到非等的操作时,我们应当采取哪些措施减少潜在风险并提高系统的稳定性? 4. 设计一个支持高并发且保持等的服务需要注意哪些方面? 5. 对比分析一下等性和事务机制之间的异同点在哪里?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值