首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >高并发下如何保证接口的幂等性?

高并发下如何保证接口的幂等性?

作者头像
芋道源码
发布2022-10-09 10:23:08
发布2022-10-09 10:23:08
1.1K00
代码可运行
举报
文章被收录于专栏:芋道源码1024芋道源码1024
运行总次数:0
代码可运行

点击上方“芋道源码”,选择“设为星标

管她前浪,还是后浪?

能浪的浪,才是好浪!

每天 10:33 更新文章,每天掉亿点点头发...

源码精品专栏

  • 原创 | Java 2021 超神之路,很肝~
  • 中文详细注释的开源项目
  • RPC 框架 Dubbo 源码解析
  • 网络应用框架 Netty 源码解析
  • 消息中间件 RocketMQ 源码解析
  • 数据库中间件 Sharding-JDBC 和 MyCAT 源码解析
  • 作业调度中间件 Elastic-Job 源码解析
  • 分布式事务中间件 TCC-Transaction 源码解析
  • Eureka 和 Hystrix 源码解析
  • Java 并发源码

来源:blog.csdn.net/weixin_43281498/

article/details/123701060


一、什么是幂等性

所谓幂等,简单地说,就是对接口的多次调用所产生的结果和调用一次是一致的。

那么我们为什么需要接口具有幂等性呢?设想一下以下情形:

  • 支付接口,重复支付会导致多次扣钱 订单接口,同一个订单可能会多次创建。
  • 在接收消息的时候,消息推送重复。如果处理消息的接口无法保证幂等,那么重复消费消息产生的影响可能会非常大。

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://gitee.com/zhijiantianya/ruoyi-vue-pro
  • 视频教程:https://doc.iocoder.cn/video/

二、幂等性的解决方案

1)唯一索引

使用唯一索引可以避免脏数据的添加,当插入重复数据时数据库会抛异常,保证了数据的唯一性。

2)乐观锁

这里的乐观锁指的是用乐观锁的原理去实现,为数据字段增加一个version字段,当数据需要更新时,先去数据库里获取此时的version版本号

代码语言:javascript
代码运行次数:0
运行
复制
select version from tablename where xxx

更新数据时首先和版本号作对比,如果不相等说明已经有其他的请求去更新数据了,提示更新失败。

代码语言:javascript
代码运行次数:0
运行
复制
update tablename set count=count+1,version=version+1 where version=#{version}
3)悲观锁

乐观锁可以实现的往往用悲观锁也能实现,在获取数据时进行加锁,当同时有多个重复请求时其他请求都无法进行操作

4)分布式锁

幂等的本质是分布式锁的问题,分布式锁正常可以通过redis或zookeeper实现;在分布式环境下,锁定全局唯一资源,使请求串行化,实际表现为互斥锁,防止重复,解决幂等。

目前主要有三种方式实现redis的分布式锁:

  • setNx 命令
  • set 命令
  • Redission 框架

具体流程图如下:

具体步骤:

  • 用户通过浏览器发起请求,服务端会收集数据,并且生成订单号 code 作为唯一业务字段。
  • 使用 redis 的 set 命令,将该订单 code 设置到 redis 中,同时设置超时时间。
  • 判断是否设置成功,如果设置成功,说明是第一次请求,则进行数据操作。
  • 如果设置失败,说明是重复请求,则直接返回成功。

需要特别注意的是:分布式锁一定要设置一个合理的过期时间,如果设置过短,无法有效的防止重复请求。如果设置过长,可能会浪费redis的存储空间,需要根据实际业务情况而定。

5)token机制

token 机制的核心思想是为每一次操作生成一个唯一性的凭证,也就是 token。一个 token 在操作的每一个阶段只有一次执行权,一旦执行成功则保存执行结果。对重复的请求,返回同一个结果。token 机制的应用十分广泛。

该方案跟之前的所有方案都有点不一样,需要两次请求才能完成一次业务操作。

  • 第一次请求获取token
  • 第二次请求带着这个token,完成业务操作。

具体流程图如下:

第一步,先获取token。

第二步,做具体业务操作。

具体步骤:

  • 用户访问页面时,浏览器自动发起获取token请求。
  • 服务端生成token,保存到redis中,然后返回给浏览器。
  • 用户通过浏览器发起请求时,携带该token。
  • 在redis中查询该token是否存在,如果不存在,说明是第一次请求,做则后续的数据操作。
  • 如果存在,说明是重复请求,则直接返回成功。
  • 在redis中token会在过期时间之后,被自动删除。

以上方案是针对幂等设计的。

如果是防重设计,流程图要改改:

需要特别注意的是:token必须是全局唯一的。



欢迎加入我的知识星球,一起探讨架构,交流源码。加入方式,长按下方二维码噢

已在知识星球更新源码解析如下:

最近更新《芋道 SpringBoot 2.X 入门》系列,已经 101 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。

提供近 3W 行代码的 SpringBoot 示例,以及超 4W 行代码的电商微服务项目。

获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

代码语言:javascript
代码运行次数:0
运行
复制
文章有帮助的话,在看,转发吧。谢谢支持哟 (*^__^*)
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-10-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 芋道源码 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、什么是幂等性
  • 二、幂等性的解决方案
    • 1)唯一索引
    • 2)乐观锁
    • 3)悲观锁
    • 4)分布式锁
    • 5)token机制
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档