Redis处理接口幂等性的方案有哪些

前言:接口幂等性问题,对于开发人员来说,是一个跟语言无关的公共问题。对于一些用户请求,在某些情况下是可能重复发送的,如果是查询类操作并无大碍,但其中有些是涉及写入操作的,一旦重复了,可能会导致很严重的后果,例如交易的接口如果重复请求可能会重复下单。接口幂等性是指用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。

一、接口幂等性

1.1、什么是接口幂等性

在HTTP/1.1中,对幂等性进行了定义。它描述了一次和多次请求某一个资源对于资源本身应该具有同样的结果,即名列前茅次请求的时候对资源产生了副作用,但是以后的多次请求都不会再对资源产生副作用。这里的副作用是不会对结果产生破坏或者产生不可预料的结果。也就是说,其任意多次执行对资源本身所产生的影响均与一次执行的影响相同。

这类问题多发于接口的:

  • insert操作,这种情况下多次请求,可能会产生重复数据。

  • update操作,如果只是单纯的更新数据,比如:update user set status=1 where id=1,是没有问题的。如果还有计算,比如:update user set status=status+1 where id=1,这种情况下多次请求,可能会导致数据错误。

1.2、为什么需要实现幂等性

在接口调用时一般情况下都能正常返回信息不会重复提交,不过在遇见以下情况时可以就会出现问题,如:

  • 前端重复提交表单: 在填写一些表格时候,用户填写完成提交,很多时候会因网络波动没有及时对用户做出提交成功响应,致使用户认为没有成功提交,然后一直点提交按钮,这时就会发生重复提交表单请求。

  • 用户恶意进行刷单: 例如在实现用户投票这种功能时,如果用户针对一个用户进行重复提交投票,这样会导致接口接收到用户重复提交的投票信息,这样会使投票结果与事实严重不符。

  • 接口超时重复提交: 很多时候 HTTP 客户端工具都默认开启超时重试的机制,尤其是第三方调用接口时候,为了防止网络波动超时等造成的请求失败,都会添加重试机制,导致一个请求提交多次。

  • 消息进行重复消费: 当使用 MQ 消息中间件时候,如果发生消息中间件出现错误未及时提交消费信息,导致发生重复消费。

本文讨论的是如何在服务端优雅地统一处理这种接口幂等性情况,如何禁止用户重复点击等客户端操作不在此次讨论范围。

1.3、引入幂等性后对系统的影响

幂等性是为了简化客户端逻辑处理,能放置重复提交等操作,但却增加了服务端的逻辑复杂性和成本,其主要是:

  • 把并行执行的功能改为串行执行,降低了执行效率。

  • 增加了额外控制幂等的业务逻辑,复杂化了业务功能;

所以在使用时候需要考虑是否引入幂等性的必要性,根据实际业务场景具体分析,除了业务上的特殊要求外,一般情况下不需要引入的接口幂等性。

二、如何设计幂等

幂等意味着一条请求的少数性。不管是你哪个方案去设计幂等,都需要一个全局少数的ID ,去标记这个请求是独一无二的。

  • 如果你是利用少数索引控制幂等,那少数索引是少数的

  • 如果你是利用数据库主键控制幂等,那主键是少数的

  • 如果你是悲观锁的方式,底层标记还是全局少数的ID

2.1、全局的少数性ID

全局少数性ID,我们怎么去生成呢?你可以回想下,数据库主键Id怎么生成的呢?

是的,我们可以使用UUID,但是UUID的缺点比较明显,它字符串占用的空间比较大,生成的ID过于随机,可读性差,而且没有递增。

我们还可以使用雪花算法(Snowflake) 生成少数性ID。

雪花算法是一种生成分布式全局少数ID的算法,生成的ID称为Snowflake IDs。这种算法由Twitter创建,并用于推文的ID。

一个Snowflake ID有64位。

  • 第1位:Java中long的较高位是符号位代表正负,正数是0,负数是1,一般生成ID都为正数,所以默认为0。

  • 接下来前41位是时间戳,表示了自选定的时期以来的毫秒数。

  • 接下来的10位代表计算机ID,防止冲突。

  • 其余12位代表每台机器上生成ID的序列号,这允许在同一毫秒内创建多个Snowflake ID。

Redis处理接口幂等性的方案有哪些

当然,全局少数性的ID,还可以使用百度的Uidgenerator,或者美团的Leaf

2.2、幂等设计的基本流程

幂等处理的过程,说到底其实就是过滤一下已经收到的请求,当然,请求一定要有一个全局少数的ID标记哈。然后,怎么判断请求是否之前收到过呢?把请求储存起来,收到请求时,先查下存储记录,记录存在就返回上次的结果,不存在就处理请求。

一般的幂等处理就是这样,如下:

Redis处理接口幂等性的方案有哪些

三、接口幂等性常见解决方案

3.1、下游传递少数请求编号

可能会想到的是,只要请求有少数的请求编号,那么就能借用Redis做这个去重——只要这个少数请求编号在Redis存在,证明处理过,那么就认为是重复的。

方案描述:

所谓少数请求序列号,其实就是每次向服务端请求时候附带一个短时间内少数不重复的序列号,该序列号可以是一个有序 ID,也可以是一个订单号,一般由下游生成,在调用上游服务端接口时附加该序列号和用于认证的 ID。

当上游服务器收到请求信息后拿取该 序列号 和下游 认证ID 进行组合,形成用于操作 Redis 的 Key,然后到 Redis 中查询是否存在对应的 Key 的键值对,根据其结果:

  • 如果存在,就说明已经对该下游的该序列号的请求进行了业务处理,这时可以直接响应重复请求的错误信息。

  • 如果不存在,就以该 Key 作为 Redis 的键,以下游关键信息作为存储的值(例如下游商传递的一些业务逻辑信息),将该键值对存储到 Redis 中 ,然后再正常执行对应的业务逻辑即可。

适用操作:

  • 插入操作

  • 更新操作

  • 删除操作

使用限制:

  • 要求第三方传递少数序列号;

  • 需要使用第三方组件 Redis 进行数据效验;

主要流程:

Redis处理接口幂等性的方案有哪些

主要步骤:

  • 下游服务生成分布式 ID 作为序列号,然后执行请求调用上游接口,并附带“少数序列号”与请求的“认证凭据ID”。

  • 上游服务进行安全效验,检测下游传递的参数中是否存在“序列号”和“凭据ID”。

  • 上游服务到 Redis 中检测是否存在对应的“序列号”与“认证ID”组成的 Key,如果存在就抛出重复执行的异常信息,然后响应下游对应的错误信息。如果不存在就以该“序列号”和“认证ID”组合作为 Key,以下游关键信息作为 Value,进而存储到 Redis 中,然后正常执行接来来的业务逻辑。

上面步骤中插入数据到 Redis 一定要设置过期时间。这样能保证在这个时间范围内,如果重复调用接口,则能够进行判断识别。如果不设置过期时间,很可能导致数据无限量的存入 Redis,致使 Redis 不能正常工作。

3.2、防重 Token 令牌

方案描述:

针对客户端连续点击或者调用方的超时重试等情况,例如提交订单,此种操作就可以用 Token 的机制实现防止重复提交。简单的说就是调用方在调用接口的时候先向后端请求一个全局 ID(Token),请求的时候携带这个全局 ID 一起请求(Token 较好将其放到 Headers 中),后端需要对这个 Token 作为 Key,用户信息作为 Value 到 Redis 中进行键值内容校验,如果 Key 存在且 Value 匹配就执行删除命令,然后正常执行后面的业务逻辑。如果不存在对应的 Key 或 Value 不匹配就返回重复执行的错误信息,这样来保证幂等操作。

使用限制:

  • 需要生成全局少数 Token 串;

  • 需要使用第三方组件 Redis 进行数据效验;

主要流程:

  • 服务端提供获取 Token 的接口,该 Token 可以是一个序列号,也可以是一个分布式 ID 或者 UUID 串。

  • 客户端调用接口获取 Token,这时候服务端会生成一个 Token 串。

  • 然后将该串存入 Redis 数据库中,以该 Token 作为 Redis 的键(注意设置过期时间)。

  • 将 Token 返回到客户端,客户端拿到后应存到表单隐藏域中。

  • 客户端在执行提交表单时,把 Token 存入到 Headers 中,执行业务请求带上该 Headers。

  • 服务端接收到请求后从 Headers 中拿到 Token,然后根据 Token 到 Redis 中查找该 key 是否存在。

  • 服务端根据 Redis 中是否存该 key 进行判断,如果存在就将该 key 删除,然后正常执行业务逻辑。如果不存在就抛异常,返回重复提交的错误信息。

注意,在并发情况下,执行 Redis 查找数据与删除需要保证原子性,否则很可能在并发下无法保证幂等性。其实现方法可以使用分布式锁或者使用 Lua 表达式来注销查询与删除操作。

到此,关于“Redis处理接口幂等性的方案有哪些”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!

文章标题:Redis处理接口幂等性的方案有哪些,发布者:亿速云,转载请注明出处:https://worktile.com/kb/p/21975

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
亿速云的头像亿速云认证作者
上一篇 2022年8月31日 下午11:29
下一篇 2022年8月31日 下午11:31

相关推荐

  • Web应用防火墙JXWAF怎么部署

    JXWAF概述 JXWAF是一种开源的Web应用程序防火墙,可用于防护SQL注入漏洞,XSS漏洞,命令执行突破等OWASP常见攻击,CC攻击等,避免网站数据泄露,保障网站可用和安全性。 功能特性 1、Web应用攻击防护 基于语义识别防护引擎防御SQL注入,XSS攻击,Webshell添加,目录遍历扩…

    2022年9月22日
    52800
  • 如何实现Web日志分析

    1 、Web日志 Web访问日志记录了Web服务器接收处理请求及运行时错误等各种原始信息。通过对WEB日志进行的安全分析,不仅可以帮助我们定位攻击者,还可以帮助我们还原攻击路径,找到网站存在的安全漏洞并进行修复。 我们来看一条Apache的访问日志: 127.0.0.1 – – [11/Jun/20…

    2022年9月24日
    47400
  • 如何通过jquery实现ajax调用

    能通过jquery来实现ajax调用。方法:1、用load()方法实现ajax请求,语法为“$(selector).load(url,…)”;2、用post()和get()方法,对应http请求中的POST、GET,语法为“$post(‘url’,{……

    2022年9月8日
    41400
  • 如何进行Web权限维持分析

    前言 权限维持,在红蓝对抗中,我觉得其意义在于两点:一是防止已获取的权限被蓝队破坏;二是防止其他红队获取到相同的权限(虽然有点缺德。。。)。 其他情况下的非法用途就不说了。 权限维持的原则我觉得就是不能影响原来业务的正常运行。(比如改后台密码导致管理员不能登录,修改文件夹读写权限导致正常的文件不能上…

    2022年9月24日
    49100
  • mysql如何对列求和

    在mysql中,可以使用SUM()函数来对列求和;SUM()是一个求总和的函数,可以返回指定列值的总和,语法“SELECT SUM(DISTINCT 列名) FROM 表名;”,“DISTINCT”运算符允许计算集合中的不同值;SUM()函数在计算时,会忽略列值为NULL的行。 本教程操作环境:wi…

    2022年9月22日
    1.6K00
  • 如何进行自动化web渗透测试框架的运用分析

    关于Vajar Vajra是一个自动化的Web渗透测试框架,它可以帮助广大安全研究人员在Web应用程序渗透测试期间自动执行无聊的侦察任务以及针对多个目标的相同扫描。Vajra具有高度可定制特性,允许研究人员自定义扫描范围,我们无需针对目标执行所有的扫描,我们可以根据自己的需要来选择需要执行的扫描任务…

    2022年9月22日
    49700
  • 如何使用exp进行SQL报错注入

    0x01 前言概述 小编又在MySQL中发现了一个Double型数据溢出。当我们拿到MySQL里的函数时,小编比较感兴趣的是其中的数学函数,它们也应该包含一些数据类型来保存数值。所以小编就跑去测试看哪些函数会出现溢出错误。然后小编发现,当传递一个大于709的值时,函数exp()就会引起一个溢出错误。…

    2022年9月6日
    66800
  • 怎么用Intellij IDEA创建web项目

    Idea创建web项目 1.打开idea,选择file->New->Project 2.点击Java,点击下一步. 3.修改项目名。 4. 右键项目,选择add framework support 5. 完成之后,项目结构变成了这样 6. 接下来,我们在WEB-INF下创建classes…

    2022年8月30日
    96900
  • 如何进行电子钱包APP漏洞分析

    雷蛇支付(Razer Pay)在新加坡和马来西亚被广泛使用,在该篇Writeup中,作者通过APP逆向分析,利用Frida调试,发现了雷蛇支付电子钱包(Razer Pay Ewallet)中的用户签名(Signature)生成漏洞,由此可读取雷蛇支付用户的聊天记录、删除用户绑定的银行账户并窃取用户个…

    2022年9月13日
    55600
  • CDR最新版本的图框精确剪裁位置在哪

    CDR最新版本的图框精确剪裁: 答:在“对象”工具栏下。 1、CDR最新版本将图框精确剪裁改名为“PowerClip”了,所以找不到。 2、我们只需要点击上方“对象”按钮,将鼠标移动到“PowerClip”就可以使用图框精确剪裁了。 3、这是上一代版本的图框精确剪裁,同样在“对象”下,不过是中文所以…

    2022年9月24日
    72700
站长微信
站长微信
电话联系

400-800-1024

工作日9:30-21:00在线

分享本页
返回顶部