架构师之路系列:接口幂等性是个什么东东?如何实现接口幂等设计?

举报
慕枫技术笔记 发表于 2022/01/19 23:41:14 2022/01/19
【摘要】 幂等实际是一个数学上的概念,在数学上如果函数满足 f(x) = f(f(x)),那么我们称函数f具备幂等性。

怎么理解接口幂等?

幂等实际是一个数学上的概念,在数学上如果函数满足 f(x) = f(f(x)),那么我们称函数f具备幂等性。举个栗子,假设f(x) =|x|,即函数f表示取x的绝对值,那么f(x) = f(f(x))也成立,即f(x) =||x| |。说完了幂等的原始概念,我们再来看下在编程领域,幂等指的又是什么,我们先来看下百度百科的解释。

在编程中一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。幂等函数,或幂等方法,是指可以使用相同参数重复执行,并能获得相同结果的函数。这些函数不会影响系统状态,也不用担心重复执行会对系统造成改变。例如,“setTrue()”函数就是一个幂等函数,无论多次执行,其结果都是一样的.更复杂的操作幂等保证是利用唯一交易号(流水号)实现。

那么我们怎么理解接口幂等呢?举个简单的例子,我们经常用的秒杀服务,在秒杀结束前,我们会疯狂的点击收集屏幕的下单按钮,但是对于秒杀而言,一个用户只能买一件,所以无论你点了多少次,要么没有秒杀到,要么秒杀到,库存只会减1,不会因为你请求了多少,或者系统因为网络重试了多少次,而改变系统的资源情况,多次操作的结果都是一致的,这种情况我们就称系统具备幂等性。

为什么要进行接口幂等设计?

如果我们不对接口进行幂等设计会导致什么问题呢?可以想象一下如果我们在京东上面下单买书,但是扣了两次钱,会有什么结果?再比如,你在银行汇钱的时候,本来要汇10000块,但是因为网络抖动原因,进行了重试,导致汇了30000块,你是不是得炸锅了。
从上面的例子我们可以知道,如果我们不做幂等设计,在一些情况下很可能会出现与我们业务期望不一样的情况,甚至会发生资损的情况,造成客户财产损失,逐渐丧失对于平台的信心,最终导致客户流失。因此我们必须要重视服务幂等问题,确保不出现上述的业务异常情况。

有哪些常见的幂等设计方案?

1、数据库唯一索引

拿用户注册这个场景来说,为了防止连续点击造成的用户信息重复的问题,我们可以在数据库中通过设置用户名、电话号码等字段的唯一性索引的方式来实现幂等,即便是出现了连续点击进行用户创建,但是在数据库层面是不会对重复数据进行入库保存的,从而达到用户服务注册接口实现幂等的目的,但是如果全靠数据库来保证的话,数据库的压力会比较大,因为入库的时候数据库要判断是否唯一,在数据量大的时候非常耗性能。
alter tableuseradd UNIQUE KEYun_user_phone(phone);

image.png

2、使用Redis

上面说到唯一键会导致数据库性能下降,那么有更好的解决方案吗?如下业务,订单服务生成订单消息后发送订单消息到MQ中,库存服务根据订单信息来扣减自己的库存。但是由于网络原因,MQ迟迟未收到库存服务的消费成功消息,因此又对库存服务进行了消息投递,因而产生了两个相同订单code的订单,而此时库存服务实际第一次已经消费成功。那么库存服务如何保证幂等呢?我们可以借助于Redis来实现幂等,首先我们通过以业务code未唯一key进行redis设置,这里的业务code就是订单号,保证全局唯一,使用setNx命令。如果可以设置成功,说明是第一次设置,那么可以继续后续的业务流程,进行库存扣减。如果设置不成功,则表明此时Redis已经有对应的订单code了,本次操作属于无效请求,直接返回,不继续后续的业务流程处理。

image.png

3、先查询再进行数据操作

在进行数据插入的时候,我们可以先去查询数据是否存在,如果不存在则进行插入操作,如果已存在那么就不再进行后续操作。

image.png

这里需要注意的是幂等和防重的区别,幂等实际是包含防重的。为什么这么说呢?防重实际上指的是防止多次请求重复执行,导致系统业务异常。而幂等强调的是即使执行了业务,多次执行和一次执行的效果应该是一致的。说起来好像有点拗口,可以这么理解,重复请求是人为操作的,所以要过滤掉重复的,如秒杀。但是幂等说明的是在微服务内部,由于存在服务间的分布式调用,如果第一次调用未收到响应,会进行第二次调用来进行重试,那么此时系统需要保证两次调用达到的业务效果是一致的。因此幂等实际包含防重操作的。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。