点击蓝色“ 程序猿DD ”关注我
回复“ 资源 ”获取独家整理的学习资料!
来源:http://tinyurl.com/y5k2sx5t
>>阿里云8月最新优惠,点击查看<<
幂等性, 通俗的说就是一个接口, 多次发起同一个请求, 必须保证操作只能执行一次 比如:
订单接口, 不能多次创建订单
支付接口, 重复支付同一笔订单只能扣一次钱
支付宝回调接口, 可能会多次回调, 必须处理重复回调
普通表单提交接口, 因为网络超时等原因多次点击提交, 只能成功一次 等等
唯一索引 -- 防止新增脏数据
token机制 -- 防止页面重复提交
悲观锁 -- 获取数据的时候加锁(锁表或锁行)
乐观锁 -- 基于版本号version实现, 在更新数据那一刻校验数据
分布式锁 -- redis(jedis、redisson)或zookeeper实现
状态机 -- 状态变更, 更新数据时判断状态
本文采用第2种方式实现, 即通过redis + token机制实现接口幂等性校验
为需要保证幂等性的每一次请求创建一个唯一标识 token
, 先获取 token
, 并将此 token
存入redis, 请求接口时, 将此 token
放到header或者作为请求参数请求接口, 后端接口判断redis中是否存在此 token
:
如果存在, 正常处理业务逻辑, 并从redis中删除此 token
, 那么, 如果是重复请求, 由于 token
已被删除, 则不能通过校验, 返回 请勿重复操作
提示
如果不存在, 说明参数不合法或者是重复请求, 返回提示即可
springboot
redis
@ApiIdempotent
注解 + 拦截器对请求进行拦截
@ControllerAdvice全局异常处理
压测工具: jmeter
本文重点介绍幂等性核心实现, 关于 springboot如何集成redis 、 ServerResponse 、 ResponseCode 等细枝末节不在本文讨论范围之内, 有兴趣的小伙伴可以查看作者的Github项目: https://github.com/wangzaiplus/springboot/tree/wxw
pom
JedisUtil
自定义注解 @ApiIdempotent
ApiIdempotentInterceptor
拦截器
TokenServiceImpl
TestApplication
OK, 目前为止, 校验代码准备就绪, 接下来测试验证
获取 token
的控制器 TokenController
TestController
, 注意 @ApiIdempotent
注解, 在需要幂等性校验的方法上声明此注解即可, 不需要校验的无影响
获取 token
查看redis
测试接口安全性: 利用jmeter测试工具模拟50个并发请求, 将上一步获取到的token作为参数
header或参数均不传token, 或者token值为空, 或者token值乱填, 均无法通过校验, 如token值为"abcd"
上图中, 不能单纯的直接删除token而不校验是否删除成功, 会出现并发安全性问题, 因为, 有可能多个线程同时走到第46行, 此时token还未被删除, 所以继续往下执行, 如果不校验 jedisUtil.del(token)
的删除结果而直接放行, 那么还是会出现重复提交问题, 即使实际上只有一次真正的删除操作, 下面重现一下
稍微修改一下代码:
再次请求
再看看控制台
虽然只有一个真正删除掉token, 但由于没有对删除结果进行校验, 所以还是有并发问题, 因此, 必须校验
其实思路很简单, 就是每次请求保证唯一性, 从而保证幂等性, 通过拦截器+注解, 就不用每次请求都写重复代码, 其实也可以利用spring aop实现。
留言交流不过瘾? 添加微信: zyc_enjoy
根据指引加入各种主题讨论群
今日问题 :
(留言说说你的答案吧,明日推文公布答案)
昨日答案 : C
这道应该怎么解析呢?直接在脑海里模拟吧,不然就找一张草稿红画一画,能很快得出答案。这道题中被拼合的图形还可以翻转,其实这类拼合类的图形推理题,个人感觉大多数都规定被拼合的图形只能上下左右平移,不能有其它行为。
(昨日问题可在 昨日推文 的文末查看)
推荐阅读
百万年薪挖了个P8程序员,难道是“水货”?
你必须收藏的Github技巧
开发部署提速8倍!这款IDE插件了解一下?
攻破MySQL性能瓶颈必知的调优技巧
如何模拟将CPU、IO打满?
来星球聊聊技术人的斜杠生活
点一点“ 阅读原文 ”小惊喜在等你