首先解释一下什么是幂等?
在计算机科学中,幂等性通常指的是某些操作或接口的特性。这些操作可以安全地被重复执行多次,而不会对系统产生不同的结果或副作用。
举几个例子:
-
支付系统:
- 如果用户提交了一个支付请求,幂等的设计可以确保无论支付请求被发送多少次,账户的余额只会被扣除一次。
-
文件上传:
- 如果上传一个文件,重复上传相同的文件可以设计成只保存一次文件,避免重复文件的存储。
-
数据插入:
- 如果插入某条记录,设计成幂等的插入操作可以确保即使同一记录插入多次,数据库中只有一条记录存在.
对于一系列幂等场景我们能怎么处理来保证幂等呢?
1. 唯一标识
- 生成唯一ID:
- 为每次操作生成一个唯一的ID或请求号。例如,可以使用UUID。
- 服务端处理:
- 在服务端记录这个ID或请求号,并确保该ID对应的操作只被执行一次。
- 如果接收到相同的ID或请求号,服务端可以选择忽略该请求或返回已处理的信息,避免重复处理。
2. 去重逻辑
- 客户端或服务端去重:
- 在客户端或服务端实现去重逻辑,确保同一操作不会被重复执行。
- 存储机制:
- 可以使用缓存、数据库或其他存储机制来保存已处理的操作或请求,避免重复操作。
3. 状态检查
- 操作前状态检查:
- 在执行操作之前,检查资源的当前状态,以决定是否执行该操作。例如:
- 在支付系统中,如果订单已支付成功,则再次提交支付请求时应返回支付成功的信息,而不是重新处理支付。
- 在执行操作之前,检查资源的当前状态,以决定是否执行该操作。例如:
4. 乐观锁(悲观锁也可)
- 版本号或时间戳:
- 使用版本号或时间戳来实现乐观锁机制。
- 更新操作:
- 执行更新操作时,首先读取当前资源的版本号或时间戳,并将其与之前的值进行比较。
- 如果版本号或时间戳未发生变化,则执行更新操作;如果已变化,说明其他操作已修改资源,此时可以拒绝更新或采取其他策略。
5. 分布式锁
- 确保单点执行:
- 在分布式系统中,使用分布式锁来确保某个操作在任何时刻只被一个节点执行。
- 实现方案:
- 可使用Redis、ZooKeeper等技术实现分布式锁,确保操作的唯一性和一致性。
6. 重试机制
- 处理网络波动和异常:
- 实现重试机制来处理可能的网络波动、超时或其他异常情况。
- 重试策略:
- 设计合理的重试策略,如指数退避(Exponential Backoff)、最大重试次数等,以减少重复操作的可能性。
7. 幂等接口设计
- 接口设计原则:
- 设计API或接口时,确保接口具有幂等性。例如:
- 删除操作:多次删除同一资源时,执行一次删除操作即可。
- 查询操作:多次查询应返回相同的结果集,保证查询的一致性。
- 设计API或接口时,确保接口具有幂等性。例如:
8. 事务管理
- 数据库事务:
- 使用数据库事务来确保操作的原子性,实现业务逻辑的幂等性。
- 事务原子性:
- 在事务中执行多个操作时,要么全部成功提交,要么全部失败回滚,确保数据的一致性。
9. 使用幂等性的中间件或框架
- 中间件或框架:
- 利用已经实现幂等性逻辑的中间件或框架。例如:
- 在消息队列中,使用消息的唯一ID和幂等消费者来确保消息只被处理一次。
- 参考其实现原理,结合具体业务场景,优化系统的幂等性。
- 利用已经实现幂等性逻辑的中间件或框架。例如:
10.ToKen机制
1)当用户访问表单页面时,客户端请求服务端接口以获取唯一的Token(可以是UUID或全局ID),服务端生成的Token会被存储在Redis或数据库中。
2)用户首次提交表单时,将Token与表单一起发送至服务端,服务端会验证Token的存在性,如果Token存在,则执行业务逻辑,并在完成后销毁Token。
3)用户再次提交表单时,同样携带Token一起发送至服务端。但由于Token已被销毁,服务端无法找到对应的Token,从而拒绝重复提交请求。