Redis如何保证接口的幂等性?

在最近的一次业务升级中,遇到这样一个问题,我们设计了新的账户体系,需要在用户将应用升级之后将原来账户的数据手动的同步过来,就是需要用户自己去触发同步按钮进行同步,因为有些数据是用户存在自己本地的。那么在这个过程中就存在一个问题,要是因为网络的问题,**用户重复点击了这个按钮怎么办?**就算我们在客户端做了一些处理,在同步的过程中,不能再次点击,但是经过我最近的爬虫实践,要是别人抓到了我们的接口那么还是不安全的。

基于这样的业务场景,我就使用Redis加锁的方式,限制了用户在请求的时候,不能发起二次请求。

我们在进入请求之后首选尝试获取锁对象,那么这个锁对象的键其实就是用户的id,如果获取成功,我们判断用户时候已经同步数据,如果已同步,那么可以直接返回,提示用户已经同步,如果没有那么直接执行同步数据的业务逻辑,最后将锁释放,如果在进入方法之后获取锁失败,那么有可能就是在第一次请求还没有结束的时候,接着又发起了请求,那么这个时候是获取不到锁的,也就不会发生数据同步出现同步好几次的情况。

华丽的分割线

那么有了这个需求之后,我们就来用Redis实现以下这个代码。首先我们要知道我们要介绍一下Redis的一个方法。

那么我们想要用Redis做用户唯一的锁对象,那么它在Redis中应该是唯一的,而且还不应该被覆盖,这个方法就是存储成功之后会返回true,如果该元素已经存在于Redis实例中,那么直接返回false

setIfAbsent(key,value)

但是这中间又存在一个问题,如果在获取了锁对象之后,我们的服务挂了,那么这个时候其他请求肯定是拿不到锁的,基于这种情况的考虑我们还应该给这个元素添加一个过期时间,防止我们的服务挂掉之后,出现死锁的问题。

/**

我们整个加锁的代码逻辑已经写完了,我们来分析一下,用户在进来之后,首先调用lock尝试获取锁,并进行加锁,lock()方法有三个参数分别是:key,waitTime就是用户如果获取不到锁,可以等待多久,过了这个时间就不再等待,最后一个参数就是该锁的多久后过期,防止服务挂了之后,发生死锁。

当进入lock()之后,先进行加锁操作,如果加锁成功,那么返回true,再执行我们后面的业务逻辑,如果获取锁失败,会获取当前时间再加上设置的过期时间,跟当前时间比较,如果还在等待时间内,那么就再次尝试获取锁,直到过了等待时间。

注意:在设置值的时候,我们为了防止死锁设置了一个过期时间,大家一定要注意,不要等设置成功之后再去给元素设置过期时间,因为这个过程不是一个原子操作,等你刚设置成功之后,还没等设置过期时间成功,服务直接挂了,那么这个时候就会发生死锁问题,所以大家要保证存储元素和设置过期时间一定要是原子操作。

最后我们来写个测试类测试一下

@Test

更多内容请关注“一个程序员的成长

【推荐阅读】

1、SpringBoot如何整合多个数据源,看这篇就够了

2、@JsonView注解如何优雅的忽略字段返回

3、非科班出身的程序员如何缓解职业焦虑

本文分享自微信公众号 - 一个程序员的成长(xiaozaibuluo)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )

KVM调整cpu和内存

一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid

Redis如何保证接口的幂等性? - HelloWorld