面试题:接口幂等性是什么?如何设计?

news2024/11/25 2:27:15

文章目录

  • 前言
  • 什么是接口幂等?
  • 为什么接口需要幂等性设计
    • 前端重复提交表单
    • 黑客恶意攻击
    • 接口超时重复提交
    • 消息重复消费
  • 哪些接口需要幂等?
  • 如何实现幂等
    • 前端拦截
    • 数据库唯一索引实现
    • 数据库乐观锁实现
    • 数据库悲观锁实现
    • JVM锁实现
    • 分布式锁实现
  • Token实现
  • 总结


前言

接口幂等-幂等性-接口的幂等性-分布式幂等性-如何保证幂等-幂等性实现方案-去重表-下单幂等-支付幂等-扣还库存幂等


什么是接口幂等?

在计算机中编程中,一个幂等操作的特点是其任意多次执行所产生的影响均与第一次执行的影响相同。

接口的幂等性实际上就是接口可重复调用,在调用方多次调用的情况下,接口最终得到的结果是一致的。有些接口可以天然的实现幂等性,比如查询接口,对于查询来说,你查询一次和两次,对于系统来说,没有任何影响,查出的结果也是一样

为什么接口需要幂等性设计

该问题等同于 为什么会重复调用?

前端重复提交表单

在填写一些表格时候,用户填写完成提交,很多时候会因网络波动没有及时对用户做出提交成功响应,致使用户认为没有成功提交,然后一直点提交按钮,这时就会发生重复提交表单请求。

黑客恶意攻击

例如在实现用户投票这种功能时,如果黑客针对一个用户进行重复提交投票,这样会导致接口接收到用户重复提交的投票信息,这样会使投票结果与事实严重不符。

接口超时重复提交

大部分RPC框架[比如Dubbo],为了防止网络波动超时等造成的请求失败,都会添加重试机制,导致一个请求提交多次。

消息重复消费

当使用 MQ 消息中间件时候,如果Consumer消费超时或者producer发送了消息但由于网络原因未收到ACK导致消息重发,都会导致重复消费。

哪些接口需要幂等?

幂等性的实现与判断需要消耗一定的资源,因此不应该给每个接口都增加幂等性判断,要根据实际的业务情况和操作类型来进行区分。例如,我们在进行查询操作和删除操作时就无须进行幂等性判断。

查询操作查一次和查多次的结果都是一致的,因此我们无须进行幂等性判断。删除操作也是一样,删除一次和删除多次都是把相关的数据进行删除(这里的删除指的是条件删除而不是删除所有数据),因此也无须进行幂等性判断。

所以到底哪些接口需要幂等?关于这个问题需要从具体业务出发,但是也有规律可循如下表:

在这里插入图片描述

如何实现幂等

前端拦截

前端拦截是指通过 Web 站点的页面进行请求拦截,比如在用户点击完“提交”按钮后,我们可以把按钮设置为不可用或者隐藏状态,避免用户重复点击。

该方法可以解决用户误操作提交两次表单所产生的重复提交问题。但前端拦截有一个致命的问题,如果是懂行的程序员或者黑客可以直接绕过页面的 JS 执行,直接模拟请求后端的接口,这样的话,我们前端的这些拦截就不能生效了。因此除了前端拦截一部分正常的误操作之外,后端的验证必不可少。

数据库唯一索引实现

数据库唯一索引实现方案一般只能适用于执行插入操作的过程。
在这里插入图片描述

具体流程步骤:

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

数据库乐观锁实现

数据库乐观锁方案一般只能适用于执行更新操作的过程,我们可以提前在对应的数据表中多添加一个字段,充当当前数据的版本标识。

这样每次对该数据库该表的这条数据执行更新时,都会将该版本标识作为一个条件,值为上次待更新数据中的版本标识的值。

具体流程步骤:

  • 客户端带着version字段请求服务端
  • 服务端执行update的时候需要给version+1,并且需要加version的更新条件如下SQL
 update t set stock = stock - 1 , version = version + 1 where id = #{id} and version = #{version}

数据库悲观锁实现

在这里插入图片描述
具体流程步骤:

  • 客户端通过业务id,访问服务端
  • 先查数据库是否存在该业务id,查库的时候需要加X锁
  • 如果存在则说明是重复请求,不存在则进行业务逻辑处理

JVM锁实现

JVM 锁实现是指通过 JVM 提供的内置锁如 Lock 或者是 synchronized 来实现幂等性。使用 JVM 锁来实现幂等性的一般流程为:首先通过 Lock 对代码段进行加锁操作,然后再判断此订单是否已经被处理过,如果未处理则开启事务执行订单处理,处理完成之后提交事务并释放锁,执行流程如下图所示:
在这里插入图片描述
JVM 锁存在的最大问题在于,它只能应用于单机环境,因为 Lock 本身为单机锁,所以它就不适应于分布式多机环境。

分布式锁实现

分布式锁实现解决JVM锁实现单机锁局限问题。
在这里插入图片描述
具体流程步骤:

  • 客户端先请求服务端,会拿到一个能代表这次请求业务的唯一字段
  • 将该字段以 SETNX 的方式存入 redis 中,并根据业务设置相应的超时时间
  • 如果设置成功,证明这是第一次请求,则执行后续的业务逻辑
  • 如果设置失败,则代表已经执行过当前请求,直接返回

Token实现

在这里插入图片描述
具体流程步骤:

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

注意:

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


总结

幂等性不但可以保证程序正常执行,还可以杜绝一些垃圾数据以及无效请求对系统资源的消耗。推荐使用分布式锁来实现,这样的解决方案更加通用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1171132.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

多式联运路径优化问题:基于拓扑排序的遗传算法染色体编码

一、什么是拓扑排序 在图论中,拓扑排序(Topological Sorting)是一个有向无环图(DAG, Directed Acyclic Graph)的所有顶点的线性序列。且该序列必须满足下面两个条件: 每个顶点出现且只出现一次。若存在一…

【漏洞复现】Apache_Tomcat7+ 弱口令 后台getshell漏洞

感谢互联网提供分享知识与智慧,在法治的社会里,请遵守有关法律法规 文章目录 1.1、漏洞描述1.2、漏洞等级1.3、影响版本1.4、漏洞复现1、基础环境2、漏洞扫描3、漏洞验证 说明内容漏洞编号漏洞名称Tomcat7 弱口令 && 后台getshell漏洞漏洞评级高…

私域营销必备:轻松掌握微信CRM管理方法

大家在微信私域营销中都遇到了什么问题? 比如管理时间不够,群发实效性低,自动回复无法适应变化等等。 我们可以利用微信CRM这个工具,轻松解决这些问题。 请问你们最想用这个工具解决什么问题呢? 使用微信CRM不仅可…

React 底层 Fiber 架构 简单理解

一、 背景 JS 是引擎是单线程运行的;严格来说,JS 引擎和页面渲染引擎在同一渲染线程,两者互斥。那么就会遇到这样的一种情况:当前面一个任务长期霸占CPU,后面啥事也干不了,浏览器卡死,造成极差…

latex空心小写字母、数字

公式中可用 R \R R、 E \mathbb{E} E 等空心大写字母表示集合、期望等,latex 用 \mathbb 实现。有时想用空心的小写字母(虚数单位,因 i 已用来表示下标)和数字(指示函数用空心 1),此时 \mathbb…

扩容一个新节点

1.删除nodes rm -rf nodes/ 2.挂载本地文件与创建节点 bash build_chain.sh -f ipconf -e /root/tools/fisco-bcos 3.部署节点 bash nodes/127.0.0.1/start_all.sh 4.把共享的gen_node_cert.sh文件下载到本地 cp /root/Desktop/共享文件夹/tools/gen_node_cert.sh ./…

selenium自动化测试入门 —— 操作元素对象

一、元素的常用操作 element.click() # 单击元素;除隐藏元素外,所有元素都可单击 element.submit() # 提交表单;可通过form表单元素提交表单 element.clear() # 清除元素的内容;如果可以的话 element.send_keys(‘需要输入的…

自动驾驶学习笔记(六)——Apollo安装

#Apollo开发者# 学习课程的传送门如下,当您也准备学习自动驾驶时,可以和我一同前往: 《自动驾驶新人之旅》免费课程—> 传送门 《2023星火培训【感知专项营】》免费课程—>传送门 文章目录 前言 Apollo安装 硬件配置 安装Ubuntu…

C++笔记之vector的成员函数swap()和data()

C笔记之vector的成员函数swap()和data() 标准C中的std::vector类确实有swap()和data()这两个成员函数。下面是它们的简要描述: swap(): std::vector的swap()成员函数用于交换两个向量的内容,实现了高效的交换操作,不需要复制向量的元素。这…

『PyQt5-基本控件』| 16 什么是屏幕坐标系?

16 什么是屏幕坐标系? 1 什么是屏幕坐标系?2 相关概念3 代码实现4 获取窗口坐标4.1 直接获取4.2 通过坐标系获取4.3 获取Frame坐标1 什么是屏幕坐标系? 2 相关概念 屏幕坐标系,即窗口相对于屏幕的坐标。屏幕左上角坐标称为原点坐标(0,0);窗口的坐标,即窗口的左上角相对…

UE5C++学习(一)--- 增强输入系统

一、关于增强输入系统的介绍 增强输入系统官方文档介绍 二、增强输入系统的具体使用 注:在使用方面,不会介绍如何创建项目等基础操作,如果还没有UE的使用基础,可以参考一下我之前UE4的文章,操作差别不会很大。 如上…

Daily neaty和希亦内衣洗衣机哪款好,高性价比内衣洗衣机测评

现在市面最火的小家电莫过于是内衣洗衣机,那么它是否真的好用还是只是智商税呢?但关于内衣洗衣机,很多小伙伴都会选入手来释放自己的双手的,现在内衣洗衣机品牌众多,而且Daily neaty和希亦CEYEE-ACE这两个大品牌会被许…

Java CAS是什么,它的底层原理?

文章目录 前言一、CAS是什么二、CAS底层原理1、UnSafe类(Native方法)2、CAS思想(自旋锁)3、为什么使用CAS,不用synchronized?4、CAS缺点5、ABA问题,原子引用更新? 前言 对于CAS部分…

SSD入门到精通系列-总目录

依公知及经验整理,原创保护,禁止转载。 专栏 《SSD入门到精通系列》 综述: SSD-序 [SSD综述1.1] 导论 免责声明: 本文根据公开信息整理,旨在介绍更多的存储知识,所载文章仅为作者观点,不构成投…

lv9 嵌入式开发 数据库sqlite

1 数据库基本概念 数据(Data) 能够输入计算机并能被计算机程序识别和处理的信息集合 数据库 (Database) 数据库是在数据库管理系统管理和控制之下,存放在存储介质上的数据集合 2 常用的数据库 大型数据库…

竞赛 深度学习猫狗分类 - python opencv cnn

文章目录 0 前言1 课题背景2 使用CNN进行猫狗分类3 数据集处理4 神经网络的编写5 Tensorflow计算图的构建6 模型的训练和测试7 预测效果8 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 **基于深度学习猫狗分类 ** 该项目较为新颖&a…

google scholar 显示异常流量

有时候可能会出现下图警告,导致打不开谷歌学术的界面,我们需要修改一下访问网址 在网站后面添加 .pk 或者 .pr ,如下: https://scholar.google.com.pk/https://scholar.google.com.pr/

网络变压器/网络滤波器/脉冲变压器接地电路的选择

Hqst华强盛(盈盛)电子导读:网络变压器/网络滤波器/脉冲变压器,以下都称网络变压器,它的接地在网络布置中非常重要,它可以有效地提高信号的稳定性和可靠性。 网络变压器接地的布置方式通常有以下几种: 一,单…

Rust学习日记(二)变量的使用--结合--温度换算/斐波那契数列--实例

前言: 这是一个系列的学习笔记,会将笔者学习Rust语言的心得记录。 当然,这并非是流水账似的记录,而是结合实际程序项目的记录,如果你也对Rust感兴趣,那么我们可以一起交流探讨,使用Rust来构建程…

《算法通关村—原来如此简单》

《算法通关村—原来如此简单》 理解层序遍历 我们有一个二叉树,我们如何去进行一层一层的遍历呢? 需要我们借用一个数据结构来进行遍历,数据结构就是队列。我们首先把根节点放入队列中,然后从此进行遍历。如何进行遍历&#xf…