幂等问题及解决方案
本文用于描述随分布式架构被广泛关注的接口幂等 问题, 讨论用于幂等的关键性问题和解决方案. 同时澄清一些误导性概念和方案
幂等定义
关于幂等性的定义问题普标关注两个领域 :数学领域的幂等 及 编程领域的幂等
[数学领域的幂等定义](https://baike.baidu.com/item/%E5%B9%82%E7%AD%89)
编程领域的幂等定义: 其用于描述满足下图特性的方法/接口/函数 简化称呼,后续统称接口.
为什么需要接口幂等
早期编程领域主流的架构为单体架构, 接口的调用多为进程内调用.针对每一个接口的调用都存在明确的结果 失败
OR 成功
, 随分布式架构流行越来越多的调用转变成跨网络调用, 受网络的稳定性影响调用的结果也变得不确定, 为避免引入繁琐的 write-check
编码模式. 行业专家提出幂等概念并配合重试简化编程工作.
如何标识同一个请求
每一个请求增加唯一性 UUID 字段 : 任何一次新的请求都不能复用曾经使用多的字段值
特定语义环境下的业务模型唯一性主键 : 该方法存在一定的使用局限,但在简单业务场景不是为一种可行的解决方案
何时考虑幂等
用户交互场景 : 误多次提交 OR 超时重试
分布式架构场景: 为简化编程采用重试策略应对网络超时d
消息推送场景: 为确保消息送达 Broker 重试推送 OR 业务方主动重发
关于幂等的误解
高并发和幂等有没有关系 ?
考虑接口幂等的使用背景,其诞生主要是为了解决同一个请求多次重试问题。 考虑重试的请求会导致先后两次调用同时执行, 其存在并发可能性但是很明显它和
高并发
没有关系。 所以打者高并发旗号讨论的幂等的解决方案本身就是一个伪命题
幂等的接口针对同一个请求多次调用返回同样的结果 ?
这是一个可选的结果, 接口幂等本身强调的对数据的修改只触发0/1次并没有对结果做严格限定. 当然如果结果相同肯定是可以简化使用方的编程, 但是也需要考虑一个现实: 大多数RPC调用是一个粗粒度的接口,其很有可能在修改数据的同时也会返回一组数据. 这组数据很大概率会在重试期间被其他调用方修改. 此时返回不同的结果可能会更合理
幂等的解决方案
通常接口大体分为两类 查询
和 修改
. 对于所有查询类型的接口我们认为天然幂等, 不管其执行多少次只会对数据产生0次影响. 针对修改
可以细分为 增加 , 删除, 修改(状态修改, 数字加减 ...)
澄清: 一些误导性的方案
Token 机制
Token 机制的诞生主要是用来验证用户请求是否合法的一种方式, 细细思量一下场景即可明白 Token 机制无法用于解决幂等问题
- 假设同一个请求由于重试执行两次 , 第一次执行失败(Token被使用), 按TOken机制第二次重试会被拒绝 . 很明显第二次重试变得没有意义. *其完全抛弃了幂等的初衷*
锁 (分布式锁/乐观锁/悲观锁)
根据前文我们了解到幂等和并发有一些关系, 那么锁能解决幂等问题么? 答案是不能. 锁解决的问题是并发请求的同步问题, 在所有提到锁解决幂等的方案中你会发现其需要其他机制来处理幂等, 锁只是简化了并发问题仅此而已.
总结
接口幂等性可以认为是当前架构形式下的一种为简化编程的解决方案. 在考虑自身系统的解决方案是推荐优先选择小而巧的方式, 同时一定要理清和严格区分不同的概念, 避免形成过于复杂的解决方案.
版权声明: 本文为 InfoQ 作者【Joker】的原创文章。
原文链接:【http://xie.infoq.cn/article/282e6bc4e2abb0950aca6d2ad】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论