转载

Spring Boot + Redis 实现接口幂等性 | 分布式开发必知!

点击蓝色“ 程序猿DD ”关注我

回复“ 资源 ”获取独家整理的学习资料!

Spring Boot + Redis 实现接口幂等性 | 分布式开发必知!

来源:http://tinyurl.com/y5k2sx5t

>>阿里云8月最新优惠,点击查看<< Spring Boot + Redis 实现接口幂等性 | 分布式开发必知!

一、概念

幂等性, 通俗的说就是一个接口, 多次发起同一个请求, 必须保证操作只能执行一次 比如:

  • 订单接口, 不能多次创建订单

  • 支付接口, 重复支付同一笔订单只能扣一次钱

  • 支付宝回调接口, 可能会多次回调, 必须处理重复回调

  • 普通表单提交接口, 因为网络超时等原因多次点击提交, 只能成功一次 等等

二、常见解决方案

  1. 唯一索引 -- 防止新增脏数据

  2. token机制 -- 防止页面重复提交

  3. 悲观锁 -- 获取数据的时候加锁(锁表或锁行)

  4. 乐观锁 -- 基于版本号version实现, 在更新数据那一刻校验数据

  5. 分布式锁 -- redis(jedis、redisson)或zookeeper实现

  6. 状态机 -- 状态变更, 更新数据时判断状态

三、本文实现

本文采用第2种方式实现, 即通过redis + token机制实现接口幂等性校验

四、实现思路

为需要保证幂等性的每一次请求创建一个唯一标识 token , 先获取 token , 并将此 token 存入redis, 请求接口时, 将此 token 放到header或者作为请求参数请求接口, 后端接口判断redis中是否存在此 token :

  • 如果存在, 正常处理业务逻辑, 并从redis中删除此  token , 那么, 如果是重复请求, 由于  token 已被删除, 则不能通过校验, 返回  请勿重复操作 提示

  • 如果不存在, 说明参数不合法或者是重复请求, 返回提示即可

五、项目简介

  • springboot

  • redis

  • @ApiIdempotent 注解 + 拦截器对请求进行拦截

  • @ControllerAdvice全局异常处理

  • 压测工具: jmeter

说明:

  • 本文重点介绍幂等性核心实现, 关于 springboot如何集成redisServerResponseResponseCode 等细枝末节不在本文讨论范围之内, 有兴趣的小伙伴可以查看作者的Github项目: https://github.com/wangzaiplus/springboot/tree/wxw

六、代码实现

pom

JedisUtil

自定义注解 @ApiIdempotent

  1. ApiIdempotentInterceptor 拦截器

TokenServiceImpl

TestApplication

OK, 目前为止, 校验代码准备就绪, 接下来测试验证

七、测试验证

获取 token 的控制器 TokenController

TestController , 注意 @ApiIdempotent 注解, 在需要幂等性校验的方法上声明此注解即可, 不需要校验的无影响

获取 token

Spring Boot + Redis 实现接口幂等性 | 分布式开发必知!

查看redis

Spring Boot + Redis 实现接口幂等性 | 分布式开发必知!

测试接口安全性: 利用jmeter测试工具模拟50个并发请求, 将上一步获取到的token作为参数

Spring Boot + Redis 实现接口幂等性 | 分布式开发必知!

Spring Boot + Redis 实现接口幂等性 | 分布式开发必知!

header或参数均不传token, 或者token值为空, 或者token值乱填, 均无法通过校验, 如token值为"abcd"

Spring Boot + Redis 实现接口幂等性 | 分布式开发必知!

八、注意点(非常重要)

Spring Boot + Redis 实现接口幂等性 | 分布式开发必知!

上图中, 不能单纯的直接删除token而不校验是否删除成功, 会出现并发安全性问题, 因为, 有可能多个线程同时走到第46行, 此时token还未被删除, 所以继续往下执行, 如果不校验 jedisUtil.del(token) 的删除结果而直接放行, 那么还是会出现重复提交问题, 即使实际上只有一次真正的删除操作, 下面重现一下

稍微修改一下代码:

Spring Boot + Redis 实现接口幂等性 | 分布式开发必知!

再次请求

Spring Boot + Redis 实现接口幂等性 | 分布式开发必知!

再看看控制台

Spring Boot + Redis 实现接口幂等性 | 分布式开发必知!

虽然只有一个真正删除掉token, 但由于没有对删除结果进行校验, 所以还是有并发问题, 因此, 必须校验

九、总结

其实思路很简单, 就是每次请求保证唯一性, 从而保证幂等性, 通过拦截器+注解, 就不用每次请求都写重复代码, 其实也可以利用spring aop实现。

留言交流不过瘾? 添加微信: zyc_enjoy

根据指引加入各种主题讨论群

每日一问

今日问题

Spring Boot + Redis 实现接口幂等性 | 分布式开发必知!

(留言说说你的答案吧,明日推文公布答案)

昨日答案 C

这道应该怎么解析呢?直接在脑海里模拟吧,不然就找一张草稿红画一画,能很快得出答案。这道题中被拼合的图形还可以翻转,其实这类拼合类的图形推理题,个人感觉大多数都规定被拼合的图形只能上下左右平移,不能有其它行为。

(昨日问题可在 昨日推文 的文末查看)

推荐阅读

  • 百万年薪挖了个P8程序员,难道是“水货”?

  • 你必须收藏的Github技巧

  • 开发部署提速8倍!这款IDE插件了解一下?

  • 攻破MySQL性能瓶颈必知的调优技巧

  • 如何模拟将CPU、IO打满?

来星球聊聊技术人的斜杠生活

Spring Boot + Redis 实现接口幂等性 | 分布式开发必知!

点一点“ 阅读原文 ”小惊喜在等你

原文  http://mp.weixin.qq.com/s?__biz=MzAxODcyNjEzNQ==&mid=2247488043&idx=1&sn=ad4d90c12a9284427580b2e494bf1079
正文到此结束
Loading...