京东面试官:接口的幂等性怎么设计?

互联网架构师

共 1896字,需浏览 4分钟

 ·

2021-09-21 20:40

互联网架构师后台回复 2T 有特别礼包
上一篇:深夜看了张一鸣的微博,让我越想越后怕

什么是幂等?


看一下维基百科怎么说的:



幂等性:多次调用方法或者接口不会改变业务状态,可以保证重复调用的结果和单次调用的结果一致。


使用幂等的场景


1、前端重复提交


用户注册,用户创建商品等操作,前端都会提交一些数据给后台服务,后台需要根据用户提交的数据在数据库中创建记录。如果用户不小心多点了几次,后端收到了好几次提交,这时就会在数据库中重复创建了多条记录。这就是接口没有幂等性带来的 bug。


2、接口超时重试


对于给第三方调用的接口,有可能会因为网络原因而调用失败,这时,一般在设计的时候会对接口调用加上失败重试的机制。如果第一次调用已经执行了一半时,发生了网络异常。这时再次调用时就会因为脏数据的存在而出现调用异常。


3、消息重复消费


在使用消息中间件来处理消息队列,且手动 ack 确认消息被正常消费时。如果消费者突然断开连接,那么已经执行了一半的消息会重新放回队列。


当消息被其他消费者重新消费时,如果没有幂等性,就会导致消息重复消费时结果异常,如数据库重复数据,数据库数据冲突,资源重复等。


解决方案


1、token 机制实现


通过token 机制实现接口的幂等性,这是一种比较通用性的实现方法。


示意图如下:

具体流程步骤:


  1. 客户端会先发送一个请求去获取 token,服务端会生成一个全局唯一的 ID 作为 token 保存在 redis 中,同时把这个 ID 返回给客户端
  2. 客户端第二次调用业务请求的时候必须携带这个 token
  3. 服务端会校验这个 token,如果校验成功,则执行业务,并删除 redis 中的 token
  4. 如果校验失败,说明 redis 中已经没有对应的 token,则表示重复操作,直接返回指定的结果给客户端


注意:


  1. 对 redis 中是否存在 token 以及删除的代码逻辑建议用 Lua 脚本实现,保证原子性
  2. 全局唯一 ID 可以用百度的 uid-generator、美团的 Leaf 去生成


2、基于 mysql 实现


这种实现方式是利用 mysql 唯一索引的特性。


示意图如下:

具体流程步骤:


  1. 建立一张去重表,其中某个字段需要建立唯一索引
  2. 客户端去请求服务端,服务端会将这次请求的一些信息插入这张去重表中
  3. 因为表中某个字段带有唯一索引,如果插入成功,证明表中没有这次请求的信息,则执行后续的业务逻辑
  4. 如果插入失败,则代表已经执行过当前请求,直接返回


3、基于 redis 实现


这种实现方式是基于 SETNX 命令实现的


SETNX key value:将 key 的值设为 value ,当且仅当 key 不存在。若给定的 key 已经存在,则 SETNX 不做任何动作。


该命令在设置成功时返回 1,设置失败时返回 0。


示意图如下:

具体流程步骤:



总结


这几种实现幂等的方式其实都是大同小异的,类似的还有使用状态机、悲观锁、乐观锁的方式来实现,都是比较简单的。


总之,当你去设计一个接口的时候,幂等都是首要考虑的问题,特别是当你负责设计转账、支付这种涉及到 money 的接口,你要格外注意喽!



感谢您的阅读,也欢迎您发表关于这篇文章的任何建议,关注我,技术不迷茫!小编到你上高速。

    · END ·
最后,关注公众号互联网架构师,在后台回复:2T,可以获取我整理的 Java 系列面试题和答案,非常齐全


正文结束


推荐阅读 ↓↓↓

1.不认命,从10年流水线工人,到谷歌上班的程序媛,一位湖南妹子的励志故事

2.如何才能成为优秀的架构师?

3.从零开始搭建创业公司后台技术栈

4.程序员一般可以从什么平台接私活?

5.37岁程序员被裁,120天没找到工作,无奈去小公司,结果懵了...

6.IntelliJ IDEA 2019.3 首个最新访问版本发布,新特性抢先看

7.这封“领导痛批95后下属”的邮件,句句扎心!

8.15张图看懂瞎忙和高效的区别!

一个人学习、工作很迷茫?


点击「阅读原文」加入我们的小圈子!

浏览 33
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报