首页 > 其他分享 >接口幂等性

接口幂等性

时间:2022-10-08 15:03:49浏览次数:67  
标签:请求 redis 接口 主键 token where id

01什么是接口幂等性

接口幂等性就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生副作用;比如支付场景。

02哪些情况需要防止

  • 用户多次点击按钮
  • 用户页面回退再次提交
  • 微服务相互调用,请求失败,feign触发重试机制

03什么情况下需要幂等

以sql为例,有些操作是天然幂等的。

  • select * from table where id = ?,无论执行多少次都不会改变状态,是天然幂等;
  • update table set col=1 where id = 2,无论执行成功多少次状态都是一致的,也是幂等操作;
  • delete from user where id = 1,执行多次,结果一致,具备幂等性;
  • insert into user(id, name) values(1, 'zhangsan'),如果id为主键,即使重复执行,也只会插入一条数据,具备幂等性;
  • update table set col=col+1 where col=2,每次执行的结果都会变化,不是幂等;
  • insert into user(id, name) values(1, 'zhangsan'),如果id不是主键,重复执行就会产生多条数据,不具备幂等性;

04幂等性解决方案

1、token机制

1、服务端提供了发送token的接口。在存在幂等问题的业务中,在业务执行前先去获取token,服务端会把token保存到redis中。
2、然后调用业务请求时,把token携带过去,一般放在请求头中。
3、服务端判断token是否存在redis,存在表示第一次请求,然后删除token,继续执行业务。
4、如果判断redis中不存在token,就表示是重复操作,直接返回给client,这样就保证了业务代码不被重复执行
危险性:
1、先删除token还是后删除token
(1)、先删除可能导致业务没有执行,重试还带上之前token,由于防重设置导致
(2)、后删除可能导致,业务处理成功,但是服务挂了,没有删除token,后面又被执行
2、token的获取、比较和删除必须是原子性的
redis中可以使用lua脚本保证原子性

if redis.call('get', KEYS[1]) == ARGV[1]
then return redis.call('del', KEYS[1])
else return 0
end

2、锁机制

1、数据库悲观锁

select * from table where id = 1 for update;
悲观锁使用时一般伴随着事物一起使用,数据锁定时间可能会很长,需要根据实际情况选用。
要注意的是,id字段一定是主键或者唯一索引,不然可能造成锁表的结果。

2、数据库乐观锁

这种方法适用于更新场景中。
update table set count = count+1,version = version + 1 where id = 1 and version = 1
根据version版本更新。乐观锁主要适用于处理读多写少的问题

3、业务层分布式锁

在获取到锁的时候先判断数据是否被处理过。

3、唯一约束

1、数据库唯一约束

插入数据,按照唯一索引进行插入,比如订单号,相同订单不会有两条记录插入。
这个机制利用了数据库的主键唯一约束的特性,解决了在insert场景下幂等问题,但主键的要求不是自增的主键,这样就需要业务生成全局唯一的主键。
如果是分库分表场景下,路由规则要保证相同请求下,落到同一个数据库同一张表中,要不然主键约束就不起效果了。

2、redis set防重

很多数据需要处理,只能被处理一次,可以计算数据的MD5将其放入redis的set,每次处理数据,先看这个MD5是否已经存在,存在就不处理。

4、防重表

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

5、全局请求唯一id

调用接口时,生成一个唯一id,redis将数据保存到集合中,存在即处理过。可以使用nginx设置每一个请求的唯一id:proxy_set_header X-Request-Id $request_id;

标签:请求,redis,接口,主键,token,where,id
From: https://www.cnblogs.com/yanghuanxi/p/16768928.html

相关文章

  • Java_函数式接口&Stream流
    Java_函数式接口&Stream流1.函数式接口1.1函数式接口概述【理解】概念有且仅有一个抽象方法的接口如何检测一个接口是不是函数式接口@FunctionalInterface放在......
  • Java_多态&抽象类&接口
    Java_多态&抽象类&接口1.多态1.1多态的概述(记忆)什么是多态​ 同一个对象,在不同时刻表现出来的不同形态多态的前提要有继承或实现关系要有方法的重写要......
  • Java基础——接口
    一、什么是接口抽象类是从多个类中抽象出来的模板,如果将这种抽象进行的更彻底,就是更加特殊的“抽象类”——接口接口是Java中的引用类型,它类似于类,它是抽象方法的集合。......
  • docker搭建yapi接口文档系统、Idea中上传接口、在线调用
    一、前言在我们后端开发中,必不可少的是接口的交接,有很多种方式,常见的就是swagger,不过这个侵入性太强了。还有就是接口文档的框架,比如今天小编带大家一起搭建的yapi,在公司......
  • 常用的 函数式接口
    函数式接口:将注解@FunctionalInterface放在一个接口上,编译器会帮我们检查这个接口是否亿实业韩式接口 JDK提供的常见函数式接口:所在包:java.util.function ......
  • 《Android底层接口与驱动开发技术详解》digest
    第一章:IDE:EclipseADTforjavadeveloper其它:ApacheAntJavaSEDevelopmentKit5或6Linux和Mac上使用ApacheAnt1.65+,Windows上使用1.7+版本;(单独的JRE是不可以的,必须......
  • #yyds干货盘点# 前端歌谣的刷题之路-第一百零七题-接口
     前言我是歌谣我有个兄弟巅峰的时候排名c站总榜19叫前端小歌谣曾经我花了三年的时间创作了他现在我要用五年的时间超越他今天又是接近兄弟的一天人生难免坎坷大不了......
  • 四、OPNSense之接口实操配置
    可关注1、CLI界面2、CLI界面配置接口识别(1)选择1,配置接口标识  DoyouwanttoconfigureLAGGsnow? 是否配置链路聚合本实验选择nDoyouwanttoconfigureV......
  • Java中List和ArrayList的区别,为什么用接口来引用对象而不是类
    区别用几句话来简单概述就是:1、List是一个接口,而ArrayList是List接口的一个实现类。2、ArrayList类继承并实现了List接口。3、因此,List接口不能被构造,也就是我们说的不能......
  • 通过openresty 解决遗留 webservice 接口安全问题
    技术一直在变革,老的技术一般都会成为现在的技术债,加上早期大家一般对于安全不是很重视(尤其是在内网环境的时候),尽管webservice是包含了ws-security安全指南的,但是很多时......