高并发下的接口如何保证幂等性
一、背景
我们实际系统中有很多操作,是不管做多少次,都应该产生一样的效果或返回一样的结果。
例如:
-
前端重复提交选中的数据,应该后台只产生对应这个数据的一个反应结果。
-
我们发起一笔付款请求,应该只扣用户账户一次钱,当遇到网络重发或系统bug重发,也应该只扣一次钱;
-
发送消息,也应该只发一次,同样的短信发给用户,用户会哭的;
-
创建业务订单,一次业务请求只能创建一个,创建多个就会出大问题。
等等很多重要的情况,这些逻辑都需要幂等的特性来支持。
二、幂等性概念
幂等(idempotent、idempotence)是一个数学与计算机学概念,常见于抽象代数中。
在编程中.一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。幂等函数,或幂等方法,是指可以使用相同参数重复执行,并能获得相同结果的函数。
这些函数不会影响系统状态,也不用担心重复执行会对系统造成改变。例如,“getUsername()和setTrue()”函数就是一个幂等函数.
更复杂的操作幂等保证是利用唯一交易号(流水号)实现.
我的理解:幂等就是一个操作,不论执行多少次,产生的效果和返回的结果都是一样的
三、技术方案
1. 查询操作 查询一次和查询多次,在数据不变的情况下,查询结果是一样的。select是天然的幂等操作
2. 删除操作 删除操作也是幂等的,删除一次和多次删除都是把数据删除。(注意可能返回结果不一样,删除的数据不存在,返回0,删除的数据多条,返回结果多个)
3.唯一索引,防止新增脏数据 比如:支付宝的资金账户,支付宝也有用户账户,每个用户只能有一个资金账户,怎么防止给用户创建资金账户多个,那么给资金账户表中的用户ID加唯一索引,所以一个用户新增成功一个资金账户记录
要点: 唯一索引或唯一组合索引来防止新增数据存在脏数据 (当表存在唯一索引,并发时新增报错时,再查询一次就可以了,数据应该已经存在了,返回结果即可)
4. token机制,防止页面重复提交
业务要求:
页面的数据只能被点击提交一次
发生原因:由于重复点击或者网络重发,或者nginx重发等情况会导致数据被重复提交
解决办法:集群环境:采用token加redis(redis单线程的,处理需要排队) 单JVM环境:采用token加redis或token加jvm内存
处理流程:
-
数据提交前要向服务的申请token,token放到redis或jvm内存,token有效时间
-
提交后后台校验token,同时删除token,生成新的token返回
token特点:
要申请,一次有效性,可以限流
注意:redis要用删除操作来判断token,删除成功代表token校验通过,如果用select+delete来校验token,存在并发问题,不建议使用
5. 悲观锁 获取数据的时候加锁获取
select * from table_xxx where id='xxx' for update;
注意:id字段一定是主键或者唯一索引,不然是锁表,会死人的
悲观锁使用时一般伴随事务一起使用,数据锁定时间可能会很长,根据实际情况选用
6. 乐观锁 乐观锁只是在更新数据那一刻锁表,其他时间不锁表,所以相对于悲观锁,效率更高。
乐观锁的实现方式多种多样可以通过version或者其他状态条件:
1、通过版本号实现
update table_xxx set name=#name#,version=version+1 where version=#version#
如非特殊说明,本站内容均来自于网友自主分享,如有任何问题均请联系我们进行处理!
猜您喜欢
MiMo Code:AI 自动编码如何辅助构建高并发缓存逻辑
2026-06-28MiMoCode是能理解项目上下文、拆解工程目标并协同执行多阶段任务的终端编码代理,擅长高并发缓存等系统级任务,具备上下文感知、Compose模式驱动、持久记忆、安全编辑与静态分析能力。 ☞☞☞AI智能聊天,问答助手,AI智能搜索,多模态理解力帮你轻松跨越从0到1的创作门槛☜☜☜ MiMoCode不是简单补几行代码的助手,而是能理解项目上下文、拆解工程目标、协同执行多阶段任务的终端编码代理。构建高...
卡普空称《识质存在》拥有专门女性团队 保证戴安娜的可爱
2026-06-22《识质存在》是卡普空为打造全新IP所做的最新尝试,于4月17日发售,不到三周便狂销200万份。随着父亲节临近,开发团队与演员们在6月18日齐聚一堂,通过纪念直播共同庆祝这一重要里程碑。 选择父亲节来举办这场活动,原因在于游戏的故事正是围绕着主角休与他的机器人伙伴戴安娜之间那种“亲人”般的情感纽带展开。游戏发售后,许多玩家都认为戴安娜那可爱又充满“女儿感”的举止,无疑激发了他们为人父母般的呵护本能。...
微信新功能官宣 合并发图更便利 聊天花样也多了
2026-06-13今天微信派公众号发文宣布更新实用功能,微信聊天现已支持多图发送后合并展示。 据介绍,当用户一次发送3张及以上图片、视频时,就能看到“发送后合并展示”选项。 发送后,多张图片或视频会以合并形式呈现在聊天窗口中,用户可通过点击进行展开或收起,快速切换展示形态。 同时,合并展示的内容还支持一键全部保存,也可以直接转发给其他朋友。 发图的方式变了,聊天的花样也更多了,无论是研究穿搭、分享旅行照片,还是用表...
怎么判断电脑硬盘是SATA2还是SATA3_接口协议与理论速度对比【经验】
2026-06-04应使用CrystalDiskInfo查看“传输模式”:显示“SATA/600”为SATA3,“SATA/300”为SATA2;该数值反映硬盘与主板实际协商速率,非标称能力或物理接口版本,需结合BIOSSATA配置和主板说明书交叉验证。 要确认你电脑硬盘当前运行在SATA2还是SATA3协议下,不能只看接口颜色或线缆外观,必须通过软件读取硬盘与主板协商后的实际工作模式——因为同一块SATA3硬盘插在...
怎样在Python Tkinter中使用线程池处理高并发的GUI数据更新?
2026-06-04不能直接用ThreadPoolExecutor更新Tkinter控件,因为Tkinter的Tcl解释器只允许主线程操作UI;子线程(包括线程池中的工作线程)调用widget方法会引发TclError或卡死;必须通过queue.Queue+root.after()将结果安全传回主线程更新。 为什么不能直接用concurrent.futures.ThreadPoolExecutor更新Tkinter控...
Python 异步编程核心解析:async/await 与真正并发的实践要点
2026-06-04本文详解Python中async/await的本质——它实现的是协程级的协作式并发,而非自动并行;关键在于await点是否让出控制权,以及被调用函数是否真正异步(如使用asyncio.sleep),而非仅标记为asyncdef。 本文详解python中`async`/`await`的本质——它实现的是协程级的**协作式并发**,而非自动并行;关键在于`await`点是否让出控制权,以及被调用函数是...
Python 异步编程核心解析:async/await 为何不等于自动并发?
2026-06-04本文深入剖析Python中async/await的本质——它实现的是协程驱动的协作式并发,而非自动并行化;关键在于函数内部是否包含可挂起的异步操作(如awaitasyncio.sleep()),而非仅靠asyncdef声明。 本文深入剖析python中`async`/`await`的本质——它实现的是协程驱动的**协作式并发**,而非自动并行化;关键在于函数内部是否包含可挂起的异步操作(如`awa...
Python怎么配置Gunicorn_工作模式选择与Worker并发数量优化调优
2026-06-02是,--workers设多会导致CPU密集型任务上下文切换频繁;I/O密集型才适用多worker,建议从2或4起步压测调整,并注意preload引发的Flask上下文错误及worker-class是否真正生效。 gunicorn启动时CPU占用飙高、响应变慢,是不是--workers设多了? 不是“越多越好”,而是要匹配实际负载类型。CPU密集型任务(比如图像处理、数值计算)设太多--worker...
怎样在Python Flask中实现多文件并发上传_处理request.files对象
2026-06-02Flask中request.files是只读的ImmutableMultiDict,需用getlist('name')获取文件列表,配合secure_filename()校验文件名、白名单检查扩展名,并用线程/进程池卸载IO/CPU耗时操作,生产环境须换Gunicorn+gevent等并发服务器。 Flask中request.files是ImmutableMultiDict,不能直接遍历修改 很多...
Python Pika库单线程模型下怎么处理高并发消费?
2026-06-02BlockingConnection因单线程同步模型导致basic_consume阻塞于start_consuming(),消息串行处理,受PythonGIL限制无法并行dispatch回调,吞吐受限;须改用SelectConnection等异步适配器获取事件循环控制权,解耦消息分发与业务处理。 单线程里用basic_consume为什么撑不住高并发? 因为pika.blockingconnect...
