稳定性三十六计-幂等设计

简介: 为什么要幂等世界上最遥远的距离是我终于鼓起勇气,对着马路对面的你大喊:“你愿意娶我吗?”我看到你面带灿烂的笑容,正回答的时候……一辆大卡车驶过,你的回答我没有听见。因各种不可抗因素产生的没有收到响应,一个简单有效的方法就是重试。被重试的接口必须是幂等的。幂等性是分布式系统设计中的一个重要概念,对超时处理、系统恢复等具有重要意义。

引子


群里发了一个总共1千元的拼手气红包,共10个。静儿点进去,额,抢到了0.05元。这个不甘心啊。退出来重新打开了这个红包,你猜怎样?显示我抢到了0.05元!


AO4H10KpI3u1AAAAABJRU5ErkJggg==.png


这就是幂等(idempotence),不管多少次请求某一个资源,对资源都具有相同的影响。幂等性是系统的接口对外一种承诺,承诺只要调用接口成功,外部多次调用对系统只产生一次副作用。

 

为什么要幂等


世界上最遥远的距离是我终于鼓起勇气,对着马路对面的你大喊:“你愿意娶我吗?”我看到你面带灿烂的笑容,正回答的时候……一辆大卡车驶过,你的回答我没有听见。


因各种不可抗因素产生的没有收到响应,一个简单有效的方法就是重试。被重试的接口必须是幂等的。


幂等性是分布式系统设计中的一个重要概念,对超时处理、系统恢复等具有重要意义。

 

保证幂等的手段


保证幂等需要理清楚两件事情:幂等条件和期望结果。


大家可能听说过保证幂等的手段有token令牌、分布式锁、去重表、数据库唯一索引等。这些所谓的幂等手段实际上防重手段。防重本质是防止一个相同的请求被当成多个不同的请求来处理。幂等的条件是知道这是一个相同的请求。防重和幂等本质上是两个不同的阶段。

 

状态机幂等


在支付场景中,创建了一个支付订单,发起了一个支付请求,这个订单不论多少次重复请求,都应该保证最多只扣款一次。即


相同支付订单ID(幂等条件) —> 最多一次扣款(期望结果)


为了实现这个目标,可以考虑使用有限状态机。


有限状态机(Finite-state machine FSM),又称有限状态自动机,简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。用于处理复杂的状态转换。


在这个支付的例子中,为了化简,不考虑退款、取消订单等复杂的状态,只考虑未支付和已支付两种状态之间的转换。


D067NpZak1c8AAAAAElFTkSuQmCC.png


由上面的状态转换图可以看到,相同支付订单ID从未支付状态,要不就是支付不成功停留在未支付状态,要不就是支付成功,状态转移为已支付。此状态转移过程不可逆。

 

public enum OrderStateEnum {
    UNPAID {
        @Override
        public OrderStateEnum changeState() {
            if (doPay()) {
                return PAID;
            }
            return UNPAID;
        }
    },
    PAID {
        @Override
        public OrderStateEnum changeState() {
            return PAID;
        }
    };
    public abstract OrderStateEnum changeState();
    public boolean doPay() {
        //这里是逻辑伪代码,可以是发起下游调用请求支付通道等
        return true;
    }
}


这是一个java版本的简单状态机实现。状态机里定义了一个未支付状态和其行为changeState。changeState又定义了一个未支付状态和其行为changeState。


利用状态机来实现这个幂等支付请求的设计流程图如下:


QPUmQAAAABJRU5ErkJggg==.png


参考状态机实现和上图可知,相同支付ID的请求,支付状态只能进行一次从未支付到已支付的转换。从而保证了其幂等性。

 

按目标幂等


先来回答一个小学生的问题:


定了一个会议,参加人数为10人。发现会议室的椅子只有5把。3个提前来到会议室的同学热心的去其他地方搬椅子进来。问:每人要搬几把椅子?


有人要说这不是把简单的问题复杂了吗?大家看到椅子不够就去搬,看够10把椅子了就不搬就可以了。对了,这其实是一个很好的解题思路,完全可以用在设计当中,就是按目标幂等。


相同会议ID(幂等条件) —> 总数10把椅子(期望结果)


利用按目标幂等来实现这个总数10把椅子请求的设计流程图如下:


+MhZs8eAx0QAAAABJRU5ErkJggg==.png


参考状态机实现和上图可知,相同支付ID的请求,支付状态只能进行一次从未支付到已支付的转换。从而保证了其幂等性。

 

总结


支持幂等是一个接口的基本素养



相关文章
|
4月前
|
消息中间件 监控 Kubernetes
别再乱排查了!Kafka 消息积压、重复、丢失,根源基本都是 Rebalance!
大家好,我是小富~分享一次Kafka消息积压排查经历:消费者组因Rebalance导致消费能力骤降。本文详解Rebalance触发场景(消费者变更、分区扩容、订阅变化、超时等),剖析其引发的消息积压、重复消费、丢失等问题根源,并提供优化方案:调优超时参数、手动提交offset、启用粘性分配策略、保障消费幂等性。掌握这些,轻松应对Kafka常见故障!
892 0
|
设计模式 缓存 前端开发
什么是幂等性?四种接口幂等性方案详解!
本文深入分布式系统中的幂等性问题及其解决方案,涵盖数据库唯一主键、乐观锁、PRG模式和防重Token等方法,关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
什么是幂等性?四种接口幂等性方案详解!
|
存储 前端开发 安全
【面试题】: bs架构与cs架构的区别以及各自优缺点
bs架构与cs架构的区别以及各自优缺点
7363 0
|
人工智能 架构师 IDE
阿里云通义灵码重磅升级,能自主修BUG、开发应用的AI程序员来了
通义灵码AI编程能力再进化,说几句话就能开发网页
23678 9
|
存储 关系型数据库 MySQL
阿里云PolarDB解决游戏行业全球部署高并发问题
阿里云PolarDB解决游戏行业全球部署高并发问题
|
缓存 负载均衡 应用服务中间件
解决Nginx常见问题的技术指南
解决Nginx常见问题的技术指南
1115 0
|
消息中间件 监控 关系型数据库
MySQL数据实时同步到Elasticsearch:技术深度解析与实践分享
在当今的数据驱动时代,实时数据同步成为许多应用系统的核心需求之一。MySQL作为关系型数据库的代表,以其强大的事务处理能力和数据完整性保障,广泛应用于各种业务场景中。然而,随着数据量的增长和查询复杂度的提升,单一依赖MySQL进行高效的数据检索和分析变得日益困难。这时,Elasticsearch(简称ES)以其卓越的搜索性能、灵活的数据模式以及强大的可扩展性,成为处理复杂查询需求的理想选择。本文将深入探讨MySQL数据实时同步到Elasticsearch的技术实现与最佳实践。
711 0
|
存储 设计模式 编译器
软件体系结构 - 复杂指令集架构 (CISC)
【4月更文挑战第18天】软件体系结构 - 复杂指令集架构 (CISC)
762 6
|
存储
原码,补码的乘法运算
原码,补码的乘法运算
883 0
|
JSON API 数据安全/隐私保护
python小知识-数据验证和解析神器pydantic
Pydantic是一个Python库,用于数据验证和设置管理,基于类型提示提供数据模型验证。它可以用于用户输入验证、JSON序列化和解析,以及API交互中的数据校验。安装Pydantic可使用`pip install -U pydantic`或`conda install pydantic -c conda-forge`。通过定义BaseModel子类并使用Field进行约束,可以创建数据模型并进行验证。例如,定义User模型验证用户名、邮箱和年龄。Pydantic还支持自定义验证器,允许在字段赋值时执行特定逻辑,如密码强度检查和哈希处理。5月更文挑战第19天
1522 1