redis实现分布式锁来防止重复提交问题(redis锁)

1、何为重复提交
重复提交是在第一次请求已经在进行处理或处理成功的情况下,人为的进行多次操作,导致不满足幂等要求的服务多次改变状态。

2、何为幂等
幂等是其任意多次执行所产生的影响均与一次执行的影响相同(不用担心重复执行会对系统造成改变)。

3、何时使用

场景一:在网络延迟的情况下让用户有时间点击多次submit按钮导致表单重复提交

场景二:表单提交后用户点击【刷新】按钮导致表单重复提交

场景三:用户提交表单后,点击浏览器的【后退】按钮回退到表单页面后进行再次提交

4、造成影响

 因为接口重复提交,会造成脏数据,进而导致数据被覆盖或有多笔业务数据问题。

5、实现思路

这里我们用到Redis的SET命令

set(key,value,"NX","EX",expireTime);
//NX:表示如果key不存在,则设置key-value,否则返回null。
//EX:过期时间的单位/秒。

首先找到防止重复提交的标识信息,把参数组装好,这里可以使用MD5加密key,这样重复提交的请求生成的key就是一样的。请求前先获取锁,

请求结束后必须释放锁,同时我们设置锁的过期时间,可以有效防止死锁。

6、实现代码

//获取分布式锁
public synchronized boolean getRedisLock(String lockKey,String value,long expireTime){

String result=jedisCluster.set(lockKey,value,"NX","EX",expireTime);//单位秒
if("OK".equalsIgnoreCase(result)){
return true;
}else{
return false;
}
}

//释放分布式锁
public boolean releaseRedisLock(String lockKey,String value){
String script="if redis.call('get',KEYS[1])==ARGV[1] then redis.call('del',KEYS[1]) else return 0 end";
String result=jedisCluster.eval(script,Collections.singletonList(lockKey),Collections.singletonList(value));
if(1L==(Long)result){
return true;
}else{
return false;
}
}

//使用分布式锁

String key="xxx";
String value="xxx";
boolean lock=getRedisLock(key,value,2*60);//默认两分钟 
try{
if(lock){
//数据保存逻辑
}else{
//重复提交提示
}
}
catch(Exception e){
}finally{
releaseRedisLock(key,value);//释放锁
}
原文地址:https://www.cnblogs.com/e-x-c-e-ption/p/14863328.html