本篇文章首要介绍了Redis的相关常识,首要介绍了浅谈Redis处理接口幂等性的两种计划,文中经过示例代码介绍的非常详细,对咱们的学习或许作业具有必定的参阅学习价值,下面一同来看一下,希望对咱们有协助。

简单聊聊Redis处理接口幂等性的两种方案

  • 引荐学习: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视频教程
  • 本文转载自:www.php.cn/redis/49508…