范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

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

  前面针对API接口编写,专门写了一篇文章《谈一谈API接口开发,怎么编写一个比较合理严谨的接口》,今天再补充关于接口幂等性的介绍。在很多业务场景特别是并发量比较高的场景中,我们需要考虑接口幂等性,来避免一些异常数据的产生或者功能的异常,比如避免数据重复插入、订单重复支付以及库存重复递减等;
  一、什么是接口幂等性
  幂等性我们最早的时候可能是在数学中接触到,就是幂函数,以下就是几个幂函数的图像。
  幂等不仅仅是一数学概念,也是一个计算机学概念,在计算机中应用也很广泛。幂等操作的特点是一次或者任意多次执行所产生的影响均与一次执行的影响相同 ,不会因为多次的请求而产生不一样的结果。换句话说,就是我使用相同的请求参数,去请求同一个接口,不管请求多少次获取到的响应数据应该是一样的(当然这里排查程序之外的其他如网络和设备等的异常所造成的不一样的结果)。
  举个例子:我们常用的select 查询语句,以及update 根据某一条件更新字段信息的,就是我们最常见的幂等。
  select * from table_name;
  update table_name set name = "名称" where id = 1;
  这两个SQL语句无论执行多少次,对数据的影响都是一致的。第一个select只是查询,不会对数据做任何变更,肯定是幂等的,这个比较好理解。第二个也是根据特定的id来更新固定的字段,这种绝对的更新是幂等的。有人可能会提出一个疑问,更新的时候如果设置了更新时间为系统当前时间,执行update 语句,更新时间是会变化的,这种也是属于幂等。二、为什么接口需要满足幂等性
  我们先看一个很常见的例子:接口编写和联调的双方,会提前约定好接口规范,明确响应返回的状态是成功还是失败,然后我们就可以根据响应的结果状态处理相应的业务,但是可能还会出现超时或者异常等,对于这些场景,由于不确定是否成功请求了,我们一般都会选择重试。而重试就是我们一开始在幂等概念里面说到的多次执行。
  如果接口不满足幂等性,可能会产生脏数据,甚至会影响业务功能,比如我已经支付过了,因为网络等原因,没有及时反馈,你又多扣了我一笔钱,那肯定是不合理的。
  上面说到的只是一个示例,有很多场景都会产生接口幂等性的问题:网络波动等异常,未收到反馈后发起重复请求; 用户重复操作,比如多次重复提交等; 使用了失效或超时重试机制,发起的重试; 页面重复刷新; 定时任务重复执行;
  针对这些场景,为了保证系统的稳定性和业务的完整性,我们肯定需要在原有的基础上进行优化。实现方式有很多种,可以在前端页面使用节流和防抖等技术来控制重复提交,也可以在后端程序校验控制,还可以从数据库角度添加索引等等,结合实际的业务需求和改造的工作量,选择合适的方式,再通过调优和压测来进一步验证。三、http请求的幂等性要求
  说到接口操作,那就离不开数据的增删改查,说到增删改查,那我们就需要先了解一下几种请求方式 GET、DELETE、POST和PUT。
  接下来我们来看一下http请求的幂等性要求:
  GET 方法用于获取资源,不应该有副作用,所以是幂等的;
  DELETE 方法用于删除资源,有副作用,但是它应该满足幂等性。调用一次和N次对系统产生的副作用是相同的,即删掉同一条或者一批数据。请注意,幂等性并不意味着服务器必须对每个请求以相同的方式进行响应 。使用 DELETE 删除某个主键所在行的数据,第一次请求时,我们可能会收到 HTTP 200 状态代码,指示该数据已成功删除。如果我们再次发送此 DELETE 请求,则可能会收到 HTTP 404 作为响应,因为该项目已被删除。第二个请求没有更改服务器状态,因此即使我们得到不同的响应,DELETE操作也是幂等的。
  GET 和 DELETE 是比较好理解的,POST 和 PUT 相对来说比较难理解为什么一个是幂等一个非幂等。
  POST用于提交请求,可以更新或者创建资源,是非幂等的,因为一次请求添加一份新资源,二次请求则添加了两份新资源,多次请求会产生不同的结果,因此POST不是幂等操作。比如用户进行注册,每次提交都是创建一个新的用户账号,这个时候就用POST。
  而PUT用于向指定URL传送更新资源,是幂等的,PUT将A修改为B,它第一次请求时值变为了B,再进行多次此操作,最终的结果还是B,与一次执行的结果是一样的,所以PUT是幂等操作。比如修改用户密码,虽然提交的还是账户名和密码这两个必填参数,但是每次提交都只是更新该用户密码。此时就比较适合使用PUT。四、幂等性的解决方案
  解决办法分为两个方向,一个方向是客户端防止重复调用,一个是服务端进行校验。客户端防止重复提交并不是绝对可靠的,优点是实现起来比较简单。我们这里只讨论服务端的校验。
  (1)分布式锁解决方案
  ①、方案介绍用户通过浏览器发起请求,服务端收集数据,并且生成code作为唯一业务字段。 搭配缓存redis,将code以String类型存入到redis中,并设置超时时间。 判断是否设置成功,如果设置成功,说明是第一次请求,则进行数据操作。 如果设置失败,说明是重复请求,则直接返回成功,不再重复进行数据处理。
  ②、问题分析
  场景一:用户快速点击提交,连续发起两次请求。第一次请求先到达服务端,然后第二次请求由于某些原因过了一会儿才到达服务端。等第二次请求达到服务端的时候,第一次请求已经执行完毕并且释放了锁。此时第二次请求仍然能加锁成功,并且执行业务逻辑。这种情况下幂等性失效。
  场景二:客户端发起第一次请求,服务端正常执行完毕并释放了分布式锁,但由于网络原因客户端没有正常收到服务端的响应,此时客户端再次发起请求。由于第一次请求所加的分布式锁已经过期所以第二次请求仍然能够加锁成功,让后执行业务逻辑。此时幂等性失效。
  场景三:客户端连续发起多次请求,这多次请求同时到达服务端,此时开始争抢锁,谁抢到锁谁就执行,其他没有抢到锁的请求都统统不执行。这种情况能保证幂等性。
  综上,这种方式有一定的缺陷性。
  (2)数据库唯一key解决方案
  ①、适用操作
  插入操作
  ②、方案介绍根据业务需求,对数据库表中的字段设置唯一索引,可以是单一索引,也可以是联合索引。 在接口做插入操作的时候,第一次请求时数据会插入成功。后续重复的数据插入数据时,会抛出异常提示唯一索引有冲突。此时我们需要对该异常进行捕获,然后返回成功,更加直观地反馈给请求端,而不是直接反馈异常,否则终端也不好识别,以此来保证接口的幂等性。
  具体步骤用户通过浏览器发起请求,服务端收集数据。 将该数据插入mysql。 判断是否执行成功,如果成功,返回成功的响应数据。 如果执行失败,要注意区分失败的类型,捕获唯一索引冲突异常 DuplicateKeyException  ,此时直接返回成功。
  ③、优缺点分析使用起来比较简单,使用SQL脚本建立唯一索引即可,可以使用以下SQL脚本创建索引。
  CREATE INDEX index_name ON table_name (column_list); //新增索引方式1-直接创建索引 ALTER TABLE table_name ADD INDEX index_name (column_list); //新增索引方式2-修改表结构的方式添加索引编码上比较麻烦,因为每个需要保证幂等的插入类型的接口都需要去做捕获DuplicateKeyException异常的操作,代码上比较冗余。 适用面不广,只能适用于插入操作 效率不高,基于数据库的唯一key去做防重和保证插入幂等,那么相当于把压力放到了数据库上。在高并发的情况下很可能出现性能问题。
  综上,这种方式也不适合多场景的使用。
  (3)乐观锁解决方案
  ①、适用操作
  更新操作
  ②、方案介绍
  数据库乐观锁方案一般只能适用于执行更新操作的过程,我们可以提前在对应的数据表中多添加一个字段,充当当前数据的版本标识。这样每次对该数据库该表的这条数据执行更新时,都会将该版本标识作为一个条件,值为上次待更新数据中的版本标识的值。
  每次查询的时候查询出版本号,每次执行更新的时候就带上这个版本号 服务端接口收到请求后按照版本号去更新数据,每次更新后将版本号 + 1 如果重复发起请求,那么每次请求的version一定是一样的,但是只要有一次更新成功了那么数据库的版本号就+1,可以保证后面的请求更新数据库不会成功。
  ③、优缺点实现简单,只需要在表中增加一个字段即可。 适用面不广,只能适用于更新相关的场景。 效率不高,适用数据库来保证幂等性,这样就是把压力放到数据库去了,本来数据库就是很多项目的性能瓶颈。
  综上,这种方式跟数据库唯一key解决方案类似,也不适合多场景的使用。
  (4)、token解决方案
  ①、适用操作
  更新或者新增操作都可以,这种方案由于不依赖于接口内部代码进行判断,所以可以通过拦截器或AOP切面 + 注解的方式做的更加通用,仅用一个注解就能让某个接口保证幂等性。
  ②、方案介绍
  服务端需要提供一个token获取接口(该 Token 可以是一个序列号,也可以是一个分布式 ID 或者 UUID 串,反正要保证唯一性),客户端调用接口获取 Token,这时候服务端会生成一个 Token 串。 然后将该串存入 Redis 数据库中,以该 Token 作为 Redis 的键(注意设置过期时间)。 将 Token 返回到客户端,客户端拿到后应存到表单隐藏域中。 客户端在执行提交表单时,把 Token 存入到 Headers 中,执行业务请求带上该 Headers。 服务端接收到请求后从 Headers 中拿到 Token,然后根据 Token 到 Redis 中查找该 key 是否存在。 服务端根据 Redis 中是否存该 key 进行判断,如果存在就将该 key 删除,然后正常执行业务逻辑。如果不存在就抛异常,返回重复提交的错误信息。
  ③、问题分析这种方案不需要在业务代码里做幂等校验,通过AOP切面 + 注解可以做的非常通用,使用起来很方便。但需要前端多发一次请求去请求token 如果客户端连续发起调用,只要每次使用的token是一样的,那么这些连续的请求只会被处理一次。由此可以正常保证幂等性。 如果某个客户端第一次发起请求,然后服务端收到后将token从Redis中删除,接着去执行业务逻辑,但是业务逻辑执行失败了,此时有两种可能: 如果此时服务端可能会向客户端返回执行失败,客户端收到该返回后自动重新请求一个token,然后再次发起请求重试。这样也没有任何问题。 如果此时服务端向客户端返回执行失败的过程中,由于网络或其他什么原因导致客户端无法接收到服务端返回的执行失败响应。那么此时客户端会再次使用第一次申请的token再次向服务端发送请求,但是此时服务端返回的确却是重复请求或执行成功
  总的来说这种方案实用性较强,没有明显的缺陷。
  一般来说没有任何一种幂等方案可以适用于所有场景,我们需要按照我们的实际情况来选择合适的方案即可。我们也可以采用多种方案组合使用来保证幂等性(我们可以使用token方案 + 数据库唯一key方案组合使用)。

番茄和圣女果,谁更有营养?说起番茄,大家都不陌生,市场上一年四季都有,可蔬可果,可生吃可做熟,是饭桌上的宠儿。番茄有大小之分,其中小番茄又叫圣女果,那么,番茄VS圣女果,谁更有营养?生吃熟吃?番茄和圣女果,明日正月二十三,迎接小财神,这4种食物要记得吃,寓意吉祥正月二十三是正月里的一个大日子,人们把这一天称作填仓节或者燎疳节,依照传说,这一天还是善财童子的诞辰,于是民间还流传着正月二十三,迎接小财神的习俗。迎接小财神除了要供奉祭祀之外,大冰箱里面千万不要放这5种食物,拿出来就要扔掉,快看看冰箱!冰箱里面千万不要放这5种食物,拿出来就要扔掉,快看看冰箱!随着经济水平不断提升,人们对饮食的要求也会变得越来越高。见到自己喜欢的东西也会买回来,完全不会考虑到价格问题正是因为如此,阳康后遗不要怕,试试艾灸来帮忙这是达医晓护的第4241篇文章随着新型冠状病毒感染的高峰期过去,许多阳康的患者发热等症状基本缓解,但部分人群还存在咳嗽疲劳感腹泻失眠等后遗症。艾灸疗法是一种传统中医治疗方法,可以通惊蛰到,春天来,常吃韭菜春笋香椿等,健康又养生24节气中的第三个节气惊蛰已过,惊蛰意味着春天的到来。与干燥的秋冬相比,春天雨水多,因此比较滋润,也是适合进补的季节。春季与肝脏相应,尤其适合养肝补肝。小邢给大家推荐几款春天应季并图文解读黄帝内经。素问。四气调神大论导语本系列图文尝试以信息可视化的方式解读和展示黄帝内经原文,旨在学习了解古籍的内容,以及锻炼信息可视化的能力。本人不是医学专业人士,仅从个人的角度来探讨,所有图表尽量按照原文来制作肠道不好危害大!中医清肠有三法,快试一试工作繁忙,每天三餐不定,赶上节假日,改善生活时还免不了暴饮暴食。不规律的进食习惯让很多人的肠胃出了故障,便秘的人比比皆是。其实,长期便秘,容易肥胖体臭,产生消化道疾病,脏腑功能也会横滨水手21甲府风林首夺日超杯冠军,奖金3000万日元直播吧2月12日讯2月11日进行的日本超级杯比赛,横滨水手战胜甲府风林夺得冠军,这也是横滨水手队史首次夺冠。这场在东京国立竞技场举行的日本超级杯,宣告J联赛第30个赛季的到来,最终体验ChatGPT(五)人工智能构成人工智能,算法模型皆设定随着ChatGPT概念的兴起,这些天国内也出现了很多类似ChatGPT问答的人工智能模拟机器人,小编的朋友们出了一个题目,就是希望去问问ChatGPT能不能写上一个毁灭人类的方案,适合糖尿病人吃的12种控糖主食注意不能戒主食呦!正确控糖不等于戒糖,注意不能戒主食,而是选择中低GI食物适量吃,保证充足碳水能量的同时减缓血糖上升,所以选对主食很重要。荞麦面荞麦面GI值为54,每100g中含有325千卡。非常适韭菜炒鸡蛋,到底先炒韭菜还是鸡蛋?大厨都错了!难怪不好吃春季是吃韭菜的好时候,在每年开春的时候也是韭菜大量上市的时候,而且春季头茬的韭菜,是一年当中最鲜嫩的一段时间。虽然现在我们一年四季都能够吃到韭菜,但是要说一年里哪个季节的最好吃最鲜
甘雨coser都是旅行家?下了江南上黄山,一夜播放破三百万作为国内首屈一指的二次元游戏,原神中有着相当多的角色,并且每个角色都充满了自己的个性,也获得了无数玩家的喜爱。不少玩家为了表达自己对角色的喜爱,采用COSPLAY的方式来还原角色,羊了个羊,服输咋就这么难从不知羊了个羊为何物,到深陷其中不能自拔,我突然体会到了,我自己里面的争竟之心,是有多么的强大!服个输咋就那么难呢?!话说,这个羊了个羊,其实就是一款简单的小游戏,简单到连个小孩子羊了个羊,火着活着又凉?还有谁没被羊了个羊刷屏?这几天网上羊声一片,娘XX一声,崩溃的声音,让整个网络都被这款游戏逼疯了。这篇文章我发得有点慢,不过说实话,是因为想过第二关,然后给你点建议,没想到玩了几天宝宝出生后,这些筛查一定要重视俗话说,耳聪能听到心声目明能透视心灵,让孩子耳聪目明心灵是把孩子培养成洞察天下之栋梁才俊的基础。那么,如何让孩子耳聪目明心灵呢?第一步是新生儿出生后要做好疾病筛查,特别是要借助仪器李某峰前女友再度晒出证据,涉及多位明星,一旦坐实,将进去陪吴头条创作挑战赛嘿,这里是辣条辣条之前就说了,李某某这事肯定会没完没了的。没那么轻易结束,后遗症要持续一段时间果不其然,在网红湾湾各种辟谣之后。李某某被曝光的绯闻前女友网红郭子瑜,又买红妹和孙楠离婚13年,报复一个人的方式,就是过得比他好1999年,30岁的孙楠事业爱情双丰收。他凭借着一首不见不散爆红,转头又遇到买红妹,两人见面不到一天就恋爱。那时候的孙楠,可谓是春风得意,人生无憾。然而,他的快乐,却建立在买红妹数借壳系列之西凤酒8月27日陕西西凤酒文旅产业发展公司已在西凤集团揭牌,该公司被西凤酒方面视为贯彻文旅文创融合发展战略的举措。根据规划,该公司将以文旅融合发展为主线,进一步挖掘传播西凤文化,开发西凤鲜红淡红紫黑不同颜色的圈圈说明什么?今年52岁的王女士(化名)一直很注重养生,每当头昏脑胀不舒服时,就会在家用真空拔罐器给自己拔罐。汪主任,我是不是湿气很重啊?这天,王女士因为腰背酸痛来到杭州市红十字会医院推拿科汪芳Iphone14系列第一天的发售结束了有点话想和大家说说,不吐不快先上个图片这是网络上一张今天看了最多的图片。说实话,这个灵动岛看着是挺不舒服的,因为我也买了14PM。那我就有疑问了,是什么样的阳光下会让手机屏幕变成这个灰色?这个角度是不是有点太2MONCLER1952男士系列伦敦亚文化华丽重生当下,随着亚文化风格的回潮,许多设计师也开始了新的思考。全新2Moncler1952男士系列由设计师SergioZambon打造。SergioZambon透过人类学家与波普艺术家的路易斯维尔竞技20奥兰多荣耀,王霜首发出战斩获NWSL首个助攻北京时间9月17日上午,NWSL比赛继续进行,路易斯维尔竞技女足主场对阵奥兰多荣耀女足。中国女足国脚王霜首发出战,并在第50分钟奉献一次精彩助攻。最终路易斯维尔竞技女足20取胜对手