如何保证幂等
考虑如下问题:在一个电商系统中,如果用户下单后,在模块之间及逆行远程调用的过程中,出现了问题,给用户响应了请求超时,那么会影响到用户购买,导致损失订单。
但是,如果对请求超时进行重试,那么会导致用户重复下单,用户明明点击了一次,却显示购买了两次,导致一些问题。
这里就涉及到了一个问题,接口的幂等性,即不管执行几次,它的影响都和执行一次一样。
如何保证Exactly-once
不能保证 Exactly-once 的原因主要有两个,一个是网络出现丢包或者分区等故障,另一个是远端服务发生了故障。
一般来说,在分布式系统中,实现消息的 Exactly-once 传递,主要有三种方式:一种是至少一次消息传递加消息幂等性,一种是分布式快照加状态回滚,一种是整体重做。
一次传递加幂等
该思路比较简单,就是当处理失败后,并不给用户返回请求超时,而是进行重试,保证至少请求一次成功,然后每次请求带上一个全局的唯一id,当失败重试的时候,该id并不会发生改变,成功后,将本次请求保存在数据库中,如果第二次发现该id后,并不会执行,直接返回。
分布式快照加回滚
分布式快照加状态回滚指的是,在整个分布式系统运行的过程中,定期对整个系统的状态做快照,在系统运行时,不论系统的哪个地方出现故障,就将整个系统回滚到上一个快照状态,然 后再重放上一个快照状态之后的情况,直到所有的消息都被正常处理。
但是该方式并不适合在线业务,因为对在线业务做快照很难,而且对整个系统做快照,耗费资源,而且做快照的时候会导致当前系统不可处理新的业务。
该方案只适合针对于像流式计算的场景。
整体重做
整体重做的 Exactly-once 的方式,可以看成是分布式快照加状态回滚的一种特殊情况。
Exactly-once 的挑战
重试面临的挑战
当采用重试策略来保证消息最少传递一次时,我们需要限制重试的次数,来确保不会因为重试导致系统雪崩。而且重试的时间间隔也会因为重试的次数而增加。
参考
《深入浅出分布式技术原理》