我的编程空间,编程开发者的网络收藏夹
学习永远不晚

浅谈java接口的幂等性及解决方案

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

浅谈java接口的幂等性及解决方案

一、什么情况下需要幂等

用户多次点击按钮
用户页面回退再次提交
微服务相互调用,由于网络问题,导致请求失败,feign触发重试机制

二、幂等性解决方案

2.1 token机制(令牌)

在加载页面详情时候,服务器会顺便生成一个token一起返回给前端,服务端同时也在Redis中保存这个token数据,前端并不展示这个token,但当页面点击提交按钮时候,会在携带上这个token参数,此时后端便会先校验前端提交请求的token与redis中的token是否一致,一致的话即是第一次请求,执行业务代码并在Redis中删除该token,当用户还是携带上次的验证码多次提交,此时服务器判断redis中验证码不存在,便可能是多次提交的情况,不再执行业务代码,保证业务的幂等性,不被重复执行。

问题1:先删除token还是后删除token

先删除可能导致, 业务确实没有执行,重试还带上之前token,由于防重设计导致,请求还是不能执行。后删除可能导致,业务处理成功,但是服务闪断,出现超时,没有删除token,别人继续重试,导致业务被执行两遍
解决:我们最好设计为先删除token,如果业务调用失败,就重新获取token再次请求。

问题2:如何保证token 获取、比较和删除必须是原子性

redis.get(token) 、token.equals、 redis del(token)如果这两个操作不是原子,可能导致,高并发下,都get到同样的数据,判断都成功,继续业务并发执行

解决:可以在redis使用lua脚本完成这个操作


//  redis+lua脚本 原子验证令牌防止重复提交攻击
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        String orderToken = "现在的令牌";
        //  return 0 失败  1 成功
        Long result = stringRedisTemplate.execute(new DefaultRedisScript<Long>(script, Long.class),Arrays.asList("要验证的KEY"), orderToken);

2.2 各种锁机制

1)数据库悲观锁


//0.开始事务
begin;
//1.查询出商品信息
select status from t_goods where id=1 for update;
//2.根据商品信息生成订单
insert into t_orders (id,goods_id) values (null,1);
//3.修改商品status为2
update t_goods set status=2;
//4.提交事务
commit;

2)数据库乐观锁
适用读多写少的情况


update t_goods set status=2,version=version+1 where id=#{id} and version=#{version};

3)业务层分布式锁
redison可以解决,代码实现


    @Override
    @RedisLock(lockedPrefix = "model:replace:materialId:", timeOut = 5000)
    @Transactional(rollbackFor = Exception.class)
    public void changeSpuSync(@LockedObject Integer materialId, String userName) {
        log.info("模型表监听物料档案id={}是否修改了spu", materialId);
        ModelChangeSpuReq modelChangeSpuReq = new ModelChangeSpuReq(materialId, userName);
        this.dealChangeSpuSyncModel(modelChangeSpuReq);
    }

2.3 各种唯一约束

1)数据库的唯一约束:
利用主键的唯一性
2)redis set防重:
很多数据需要处理,只能被处理一次,比如我们可以计算数据的MD5将其放入redis的set,每次处理数据,先看这个MD5是否已经存在,存在就不处理。(百度上传文件秒传机制,如果该文件已经存在,就无需重复上传)

2.4 防重表

使用订单号orderNo做为去重表的唯一索引, 把唯一索引插入去重表, 再进行业务操作,且他们在同一个事中。这个保证了重复请求时,因为去重表有唯一约束,导致请求失败,避免了幂等问题。这里要注意的是,去重表和业务表应该在同一库中,这样就保证了在同一个事务,即使业务操作失败了,也会把去重表的数据回滚。这个很好的保证了数据一致性。

2.5 全局请求唯一id

前端每次调用接口请求时,生成一个唯一id,redis将数据保存到集合中(去重),存在即处理过。
全链路tranceId:可以使用Nginx设置每一个请求的唯一id;也可方便系统的链路追踪,该id并不能解决去重问题,当A系统调用B系统,B系统是否产生重试机制时候,可以根据这个id去判断


proxy_set header X-Request-ld $request_id;

总结

总之,一般情况下,几种方式的优选级使用顺序可以这样:分布式锁 > 乐观锁 > JVM锁 > 唯一约束 > 数据库悲观锁

当然,幂等性设计不能脱离业务实际来讨论,一定要根据实际业务场景选择合适的幂等性解决方案。

到此这篇关于浅谈java接口的幂等性及解决方案的文章就介绍到这了,更多相关java接口的幂等性内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

浅谈java接口的幂等性及解决方案

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

浅谈Redis处理接口幂等性的两种方案

目录一、接口幂等性1.1、什么是接口幂等性1.2、为什么需要实现幂等性1.3、引入幂等性后对系统的影响二、如何设计幂等2.1、全局的唯一性ID2.2、幂等设计的基本流程三、接口幂等性常见解决方案3.1、下游传递唯一请求编号3.2、防重 To
2022-08-15

Redis+aop实现接口防刷(幂等)的解决方案

Redis+AOP实现接口防刷(幂等)解决方案:利用Redis的setnx命令和AOP技术,实现接口防刷功能。在接口请求前,根据请求ID在Redis中设置键值对,若成功则表示首次请求,若失败则表示重复请求,直接返回错误信息。该方案适用于防止用户重复提交订单、多次尝试登录等场景。优点在于性能高、可扩展,缺点是内存占用和存在单点故障风险。
Redis+aop实现接口防刷(幂等)的解决方案
2024-04-02

PHP接口性能瓶颈分析与解决方案(PHP接口性能瓶颈的识别与解决策略)

PHP接口性能瓶颈分析与解决方案摘要本文深入探讨PHP接口的性能瓶颈识别与解决策略,涵盖:识别瓶颈:网络延迟、服务器资源不足、数据库查询效率低、代码执行效率差、外部API调用。解决策略:优化网络延迟、提升服务器资源、优化数据库查询、提升代码执行效率、优化外部API调用等。此外,文章强调了最佳实践,例如RESTful设计、标准HTTP状态码、接口文档化和定期监控。遵循这些策略和最佳实践可以显著改善PHP接口的性能。
PHP接口性能瓶颈分析与解决方案(PHP接口性能瓶颈的识别与解决策略)
2024-04-02

linux系统挂载以及卸载USB接口的设备的解决方案

这篇文章主要介绍“linux系统挂载以及卸载USB接口的设备的解决方案”,在日常操作中,相信很多人在linux系统挂载以及卸载USB接口的设备的解决方案问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”linux
2023-06-13

Linux服务器安全性:Web接口保护策略的创新解决方案

Linux服务器Web接口安全强化方案创新的Linux服务器Web接口安全策略包括:多因素身份验证(MFA)基于风险的身份验证(RBA)入侵检测系统(IDS)Web应用程序防火墙(WAF)服务器强化安全日志记录和监视持续安全教育此外,以下解决方案提供进一步保护:基于机器学习的异常检测区块链技术云安全服务
Linux服务器安全性:Web接口保护策略的创新解决方案
2024-04-10

Linux服务器安全性:Web接口保护策略的创新解决方案

Linux服务器的安全性对于保护Web接口至关重要。以下是一些创新的解决方案来增强Web接口的安全性:1. 使用双因素认证:在Web接口登录时引入双因素认证可以提高安全性。除了常规的用户名和密码,用户需要提供第二个认证因素,如手机验证码或指
2023-10-18

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录