什么是分布式系统中的幂等性

现如今我们的系统大多拆分为分布式SOA,或者微服务,一套系统中包含了多个子系统服务,而一个子系统服务往往会去调用另一个服务,而服务调用服务无非就是使用RPC通信或者restful,既然是通信,那么就有可能再服务器处理完毕后返回结果的时候挂掉,这个时候用户端发现很久没有反应,那么就会多次点击按钮,这样请求有多次,那么处理数据的结果是否要统一呢?那是肯定的!尤其再支付场景。

幂等性:就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。举个最简单的例子,那就是支付,用户购买商品使用约支付,支付扣款成功,但是返回结果的时候网络异常,此时钱已经扣了,用户再次点击按钮,此时会进行第二次扣款,返回结果成功,用户查询余额返发现多扣钱了,流水记录也变成了两条...

在以前的单应用系统中,我们只需要把数据操作放入事务中即可,发生错误立即回滚,但是再响应客户端的时候也有可能出现网络中断或者异常等等。

在增删改查4个操作中,尤为注意就是增加或者修改:

  • 查询对于结果是不会有改变的
  • 删除只会进行一次,用户多次点击产生的结果一样
  • 修改在大多场景下结果一样
  • 增加在重复提交的场景下会出现

那么如何设计接口才能做到幂等呢?

方法一
单次支付请求,也就是直接支付了,不需要额外的数据库操作了,这个时候发起异步请求创建一个唯一的ticketId,就是门票,这张门票只能使用一次就作废,具体步骤如下:

  1. 异步请求获取门票
  2. 调用支付,传入门票
  3. 根据门票ID查询此次操作是否存在,如果存在则表示该操作已经执行过,直接返回结果;如果不存在,支付扣款,保存结果
  4. 返回结果到客户端
  5. 如果步骤4通信失败,用户再次发起请求,那么最终结果还是一样的

方法二
分布式环境下各个服务相互调用

这边就要举例我们的系统了,我们支付的时候先要扣款,然后更新订单,这个地方就涉及到了订单服务以及支付服务了。

用户调用支付,扣款成功后,更新对应订单状态,然后再保存流水。

而在这个地方就没必要使用门票ticketId了,因为会比较闲的麻烦

(支付状态:未支付,已支付)

步骤:

  1. 查询订单支付状态
  2. 如果已经支付,直接返回结果
  3. 如果未支付,则支付扣款并且保存流水
  4. 返回支付结果

如果步骤4通信失败,用户再次发起请求,那么最终结果还是一样的

对于做过支付的朋友,幂等,也可以称之为冲正,保证客户端与服务端的交易一致性,避免多次扣款。

转自:http://www.cnblogs.com/leechenxiang/p/6626629.html

  • 7
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
在设计分布式系统接口的幂等性时,可以采取以下策略: 1. 使用唯一标识符:为每个请求生成唯一的标识符(例如UUID),将该标识符作为请求的一部分,在服务端进行幂等性校验时使用。服务端可以通过记录已处理请求的标识符,避免对同一请求的重复处理。 2. 幂等性检测:在服务端对接口请求进行处理之前,检测该请求是否已经被处理过。可以通过查询数据库、缓存或日志等方式来判断该请求是否已经被处理。如果已经被处理过,则直接返回之前的结果,避免重复处理。 3. 乐观锁机制:在处理接口请求时,使用乐观锁来保证操作的原子性和幂等性。通过在数据记录添加版本号或时间戳等字段,当多个请求并发操作同一数据时,只有一个请求能够成功执行,其他请求会失败并返回适当的结果。 4. 幂等性响应标识:在接口响应返回一个唯一的标识符,该标识符可以用于客户端判断该请求是否已经被成功处理过。客户端可以保存该标识符,并在后续的请求将该标识符传递给服务端,以确保幂等性。 5. 事务处理:在进行涉及状态更新的操作时,使用事务来保证操作的原子性和幂等性。如果操作失败,事务会回滚到之前的状态,避免对同一请求的重复处理。 以上是一些常见的设计策略,可以根据具体系统的需求和特点选择适合的幂等性设计方式。同时,还需要注意在接口文档明确指定接口的幂等性要求,以便开发人员正确使用和处理接口。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值