专栏首页moon聊技术接口的幂等性的多重考虑,你会了吗?

接口的幂等性的多重考虑,你会了吗?

目录

  • 目录
  • 前言
  • 正文
    • 1 接口幂等性
    • 1.1 案例
    • 2 解决方案
    • 2.1 token机制
    • 2.2 去重表
    • 2.3 redis 的 SETNX键值
    • 2.4 状态机幂
    • 2.5 乐观锁(更新操作)
    • 2.6 悲观锁(更新操作)
  • 结语

前言

今天的主题:接口幂等性的解决方案。本来是想把对象的存储过程和内存布局肝出来的,但是临时产生了变化,哈哈,这部分内容我们留在下一期吧,有句话说的好,好事多磨,对吧。

在实际项目开发中接口是我们在开发中经常接触到的,而且是经常经常要写,每一个项目可能都会伴随着大量的接口开发,在moon来涂鸦的这几个月,基本上就是在与接口作斗争了,新需求除了业务相关就是设计表和接口编写了。

当然,在接口设计中我们要考虑很多问题,安全性,格式,设计等等,今天我们先来聊聊,在高并发环境下,接口幂等性的解决方案有哪些。

正文

1 接口幂等性

就是说在多次相同的操作下保证最终的结果是一致的。

其实这个概念还是比较简单的,很容易理解,那我们思考一个问题,如果不保证接口幂等性会有什么问题

1.1 案例

我们简单的举个例子,现在有一个接口,提供了转账的功能,a要给b转账1000元,正常情况下我们接口一次性就调用成功了,但是却因为网络抖动等其它原因没有成功,于是就开始不停的重试,突然网络好了,但是这时却连续发出去了三个请求,但是这个接口没有保证幂等性,于是从结果上来看就是a给b转了3000元,这显然是程序业务逻辑上不能接受的(其实moon可以当b的)。

2 解决方案

2.1 token机制

token机制其实是比较简单的,我们先来简单的说一下流程。

  • 首先客户端先请求服务端,服务端生成token,每次请求生成的都是一个新的token(这个token一定要设置超时时间),将token存入redis当中,然后将token返回给客户端。
  • 客户端携带刚刚返回的token请求服务端做业务请求
  • 服务端收到请求,做判断。
    • 如果token在redis中,则直接删除该token,然后继续做业务请求。
    • 如果token不在redis中,代表已经执行过当前业务了,则不执行业务。

图示如下:

token机制实现方式还是比较简单的,但是其实对于我们某些响应速度要求很高的业务不太友好,缺点就是需要多一次请求获取token的过程

正常来说是每次请都会生成一个新的token,如果有极限情况下,有两个请求都带着相同的token进来,会存在都走入判断是否存在的过程,可能都会同时查到存在,这样也会有问题,针对这种情况,我们可以在删除前判断下是否存在,存在就删除,为了保证原子性,这部分逻辑建议使用lua脚本完成

2.2 去重表

去重表的机制是根据mysql唯一索引的特性来的,我们先来说下它的流程:

  • 首先客户端先请求服务端,服务端先将这次的请求信息存入一张mysql的去重表中,这张表要根据这次请求的其中某个特殊字段建立唯一索引,或者主键索引
  • 判断是否插入成功
    • 如果插入成功,则继续做后续业务请求。
    • 如果插入失败,则代表已经执行过当前请求。

图示如下:

去重表机制的问题有两点:

  • 1.mysql容错性,也就是mysql本身如果不是高可用的那么业务可能会受到影响:
  • 2.既然是唯一索引,自然在写表的时候就没有办法用到changbuffer,每次都要从磁盘查出来判断再写入,对于一个高并发的接口来说,这些都是需要考虑的因素。

2.3 redis 的 SETNX键值

过程如下:

  • 首先客户端先请求服务端,服务端将能代表这次请求业务的唯一字段以 SETNX 的方式存入redis,并设置超时时间,超时时间可以根据业务权衡。
  • 判断是否插入成功
    • 如果插入成功,则继续做后续业务请求。
    • 如果插入失败,则代表已经执行过当前请求。

这里我们是利用了redis setnx 的特性来完成的。

setnx:只在键key不存在的情况下,将键key的值设置为value。若键key已经存在,则SETNX命令不做任何动作。命令在设置成功时返回1,设置失败时返回0

图示如下:

这种方案可以说是针对上一个方案改进的,效率也会提高很多。

2.4 状态机幂

这种机制适用于有不同状态的业务,moon的上一家公司就是这样做的。

我们的订单系统,一条订单会有多个状态,如:待付款,锁定,已付款等状态,而这些状态都是有流程和逻辑的,我们可以根据这个状态判断是否执行后续业务操作。

2.5 乐观锁(更新操作)

就是数据库中增加版本号字段,每次更新根据版本号来判断

过程如下:

  • 首先客户端先请求服务端,先查询出当前的version版本。
    • select version from .. where ..
  • 根据version版本来做sql操作
    • UPDATE .. SET ... version=(version+1) WHERE .. AND version=version;

这个图示我就不再画了,还是比较简单的

2.6 悲观锁(更新操作)

假设每一次拿数据,都有认为会被修改,所以给数据库的行上锁,也是基于数据库特性来完成。

当数据库执行select for update时会获取被select中的数据行的行锁,因此其他并发执行的select for update如果试图选中同一行则会发生排斥(需要等待行锁被释放),因此达到锁的效果。

START TRANSACTION; # 开启事务
SELETE * FROM TABLE WHERE .. FOR UPDATE;
UPDATE TABLE SET ... WHERE ..;
COMMIT; # 提交事务

本文分享自微信公众号 - moon聊技术(onetraveller_llxz),作者:moon聊技术

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-11-17

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 稳定性三十六计-幂等设计

    群里发了一个总共1千元的拼手气红包,共10个。静儿点进去,额,抢到了0.05元。这个不甘心啊。退出来重新打开了这个红包,你猜怎样?显示我抢到了0.05元!

    静儿
  • 接口幂等设计探索实践

    幂等性原本是数学上的概念,即使公式:f(x)=f(f(x)) 能够成立的数学性质。用在编程领域,则意为对同一个系统,使用同样的条件,一次请求和重复的多次请求对系...

    王炸
  • 专栏RPC实战与核心原理-第三天学习

    服务发现的作用就是实时感知集群 IP 的变化,实现接口跟服务集群节点 IP 的映射。

    程序员小王
  • 如何确保分布式场景下的并发幂等性?

    幂等是数学中的一个概念,它表示如果一个东西进行1次变换或进行N次变换之后,所产生的效果如果相同的话,就称为幂等。

    Java技术栈
  • 无处不在的幂等性

    最近接手一个项目,基于Airflow实现ETL的功能。问题是这个ETL经常出问题,然后就是修数据,虽然有Airflow的优势,但是还是相当的烦人。我们项目都是基...

    明月AI
  • 如何保证消息不被重复消费?或者说,如何保证消息消费的幂等性?

    其实这是很常见的一个问题,这俩问题基本可以连起来问。既然是消费消息,那肯定要考虑会不会重复消费?能不能避免重复消费?或者重复消费了也别造成系统异常可以吗?这个是...

    小东啊
  • 面试题:如何保证消息不被重复消费?

    其实这是很常见的一个问题,这俩问题基本可以连起来问。既然是消费消息,那肯定要考虑会不会重复消费?能不能避免重复消费?或者重复消费了也别造成系统异常可以吗?这个是...

    用户1263954
  • 分布式系统关注点——99%的人都能看懂的「补偿」以及最佳实践

    前面几篇中z哥跟你聊了聊做「高可用」的意义,以及如何做「负载均衡」和「高可用三剑客」(熔断、限流、降级,文末会附上前文连接:))。这次,我们来聊一聊在保证对外高...

    Zachary_ZF
  • java幂等性的控制(技术论坛上整理成文)

    转载自 https://blog.csdn.net/mine_song/article/details/70992385

    allsmallpig
  • Java高频面试题- 每日三连问?【Day9】 — 消息队列篇二

      在一般网络环境下,都存在一定的网络延迟、网络抖动,网络问题导致消息重复发送的情况是难以避免的,毕竟网络环境无法预知。

    浩说编程
  • 腾讯云 API 最佳实践: 善用幂等性

    有些开发者问我云服务器“创建实例”接口有一个参数“ClientToken”不知道有什么作用。本文作一个简单的解答。

    zqfan
  • 【Java8新特性】01 函数式接口和Lambda表达式你真的会了吗

    Lambada表达式可以理解为:可传递的匿名函数的一种简洁表达方式。Lambda表达式没有名称,同普通方法一样有参数列表、函数主体、返回类型等;

    爱笑的架构师
  • 分布式事务之最终一致性实现方案

    为了减少系统代价,如果中间节点处理失败,其他节点一般不会自动回滚,而是通过重试机制和人工参与的方式对失败数据进行处理,从而来保证数据最后的一致性。

    新亮
  • [性能测试实战30讲」之问题问答整理八、九、十

    HTTP 的 GET 和 POST 请求,在后端处理中有什么不同?断言的作用是什么?如何使用断言呢?

    高楼Zee
  • 正经的聊聊分布式架构中的 redis

    话还得从上次报税说起,耳边还回绕这残留的芬芳:“SX系统,这也不能点,那也不能用!”,

    用户1577699
  • 翻译连载 |《你不知道的JS》姊妹篇 |《JavaScript 轻量级函数式编程》- 第 5 章:减少副作用

    原文地址:Functional-Light-JS 原文作者:Kyle Simpson-《You-Dont-Know-JS》作者 第 5 章:减少副作用 在第 2...

    iKcamp
  • 99%的人都能看懂的分布式最佳「补偿」实践

    正如之前几篇文章所说,一次跨机器的通信可能会经过DNS 服务,网卡、交换机、路由器、负载均衡等设备,这些设备都不一定是一直稳定的,在数据传输的整个过程中,只要任...

    程序猿DD
  • 如何保证消息不被重复消费?或者说,如何保证消息消费的幂等性?

    首先,比如 RabbitMQ、RocketMQ、Kafka,都有可能会出现消息重复消费的问题,正常。因为这问题通常不是 MQ 自己保证的,是由我们开发来保证的。...

    IT技术小咖
  • 一文理解如何实现接口的幂等性

    幂等,这个词来源自数学领域。幂等性衍生到软件工程中,它的语义是指:函数/接口可以使用相同的参数重复执行, 不应该影响系统状态,也不会对系统造成改变。

    全菜工程师小辉

扫码关注云+社区

领取腾讯云代金券