为了防止用户在页面上重复点击或者同时发起多次请求,请求处理需要操作redis缓存,这个时候需要对并发边界进行并发锁控制,实现思路:

由于每个页面发起的请求带的token具备唯一性,可以将token作为锁(key),当前时间作为value进行并发锁控制,分为两个方法:acquireLock和realeaseLock

/**尝试获取锁并设置有效时间*/
53
+ public boolean acquireLock(String lock, long expired){
54
+ boolean isSuccess = false;
55
+ Jedis jedis = jedisPool.getResource();
56
+ long value = System.currentTimeMillis() + expired + 1;
57
+ long acquired = jedis.setnx(lock, String.valueOf(value));
58
+ if (acquired == 1)
59
+ isSuccess = true;
60
+ else {
61
+ long oldValue = Long.valueOf(jedis.get(lock));
62
+ //如果其他资源之前获得锁已经超时
63
+ if (oldValue < System.currentTimeMillis()){
64
+ String getValue = jedis.getSet(lock, String.valueOf(value));
65
+ if (Long.valueOf(getValue) == oldValue)
66
+ isSuccess = true;
67
+ else
68
+ isSuccess = false;
69
+ }
70
+ else isSuccess = false;
71
+ }
72
+ jedisPool.returnResource(jedis);
73
+ return isSuccess;
74
+ }
75
+
76
+ /**释放锁资源*/
77
+ public void releaseLock(String lock){
78
+ Jedis jedis = jedisPool.getResource();
79
+ long currentTime = System.currentTimeMillis();
80
+ if (currentTime < Long.valueOf(jedis.get(lock))){
81
+ jedis.del(lock);
82
+ }
83
+ jedisPool.returnResource(jedis);
84
+ }

经过代码review,对照开源的jedisLock源码,发现以上实现逻辑问题在于,对于jedisPool.getResource如果发生异常,没有对异常进行处理,在外面包装类加上如下处理:

Object runTask(Callback callback) {
Jedis jedis = null;
boolean broken = false;
try {
jedis = jedisPool.getResource();
return callback.onTask(jedis);
} catch (JedisException e) {
broken = handleJedisException(e);
} catch (Exception e) {
log.error("Redis runTask error: ", e);
} finally {
closeResource(jedis, broken);
jedis = null;
}
return null;
}
private boolean handleJedisException(JedisException jedisException) {
if (jedisException instanceof JedisConnectionException) {
log.error("Redis connection lost.", jedisException);
} else if (jedisException instanceof JedisDataException) {
if ((jedisException.getMessage() != null) && (jedisException.getMessage().indexOf("READONLY") != -1)) {
log.error("Redis connection are read-only slave.", jedisException);
} else {
// dataException, isBroken=false
return false;
}
} else {
log.error("Jedis exception happen.", jedisException);
}
return true;
}
private void closeResource(Jedis jedis, boolean conectionBroken) {
try {
if (conectionBroken) {
jedisPool.returnBrokenResource(jedis);
} else {
jedisPool.returnResource(jedis);
}
} catch (Exception e) {
log.error("return back jedis failed, will fore close the jedis.", e);
jedis.close();
}
}

Redis并发锁控制的更多相关文章

  1. 基于redis实现锁控制

    多数据源 数据源1为锁控制,数据源2自定义,可用于存储. 锁:当出现并发的时候为了保证数据的一致性,不会出现并发问题,假设,用户1修改一条信息,用户2也同时修改,会按照顺序覆盖自修改的值,为了避免这种

  2. Redis修改数据多线程并发—Redis并发锁

    本文版权归博客园和作者本人吴双共同所有 .转载爬虫请注明地址,博客园蜗牛 http://www.cnblogs.com/tdws/p/5712835.html 蜗牛Redis系列文章目录http:// ...

  3. Redis学习笔记~Redis并发锁机制

    回到目录 redis客户端驱动有很多,如ServiceStack.Redis,StackExchange.Redis等等,下面我使用ServiceStack.Redis为例,介绍一下在redis驱动中 ...

  4. redis并发锁

    1.应对并发场景 避免操作数据不一致 将对redis加锁 2.考虑到异常状况无法释放锁,导致死锁 将代码块进行try-catch处理 3.考虑try时宕机依然导致死锁 对锁添加时效性,添加过期时间 4 ...

  5. 使用Redis构建全局并发锁

    谈起Redis的用途,小伙伴们都会说使用它作为缓存,目前很多公司都用Redis作为缓存,但是使用Redis仅仅作为缓存未免太大材小用了.深究Redis的原理后你会发现它有很多用途,在很多场景下能够使用 ...

  6. Redis构建全局并发锁

    Redis构建全局并发锁 https://www.cnblogs.com/FG123/p/9990336.html 谈起Redis的用途,小伙伴们都会说使用它作为缓存,目前很多公司都用Redis作为缓 ...

  7. 【redis】基于redis实现分布式并发锁

    基于redis实现分布式并发锁(注解实现) 说明 前提, 应用服务是分布式或多服务, 而这些"多"有共同的"redis"; (2017-12-04) 笑哭, 写 ...

  8. 用压测模拟并发、并发处理(synchronized,redis分布式锁)

    使用工具:Apache an 测压命令: ab -n 100 -c 100 http://www.baidu.com -n代表模拟100个请求,-c代表模拟100个并发,相当于100个人同时访问 ab ...

  9. 使用Redis分布式锁处理并发,解决超卖问题

    一.使用Apache ab模拟并发压测 1.压测工具介绍 $ ab -n 100 -c 100 http://www.baidu.com/ -n表示发出100个请求,-c模拟100个并发,相当是100 ...

随机推荐

  1. 如何在自己的窗体(控件)中显示XAF的视图

    Form form = new Form(); DevExpress.ExpressApp.View listView = Application.CreateListView(Application ...

  2. 译\Node.js应用的持续部署

    Node.js应用的持续部署 翻译前 翻译自:https://blog.risingstack.com/continuous-deployment-of-node-js-applications/ 正 ...

  3. 根据标记清空页面中所有的input对象

    function clear1(flag) { //获取页面中所有的input对象 var inputs = document.getElementsByTagName("input&quo ...

  4. 《CSS权威指南》读书笔记

    一.css和文档层叠 css规定了冲突规则,这些规则统称为层叠.这些规则定义了样式发生冲突时以优先级高的为准. 常用的优先级判定: 1. 开发者样式>读者样式>浏览器样式(除非使用!imp ...

  5. 解决在CAPSLOCK开启情况下sendkeys大小写异常的问题

    http://files.cnblogs.com/files/liuzhaoyzz/sendkeys%E5%A4%A7%E5%B0%8F%E5%86%99.rar 首先利用GetKeyState(vb ...

  6. ireport5.6+jasperreport6.3开发(四)--以javabean为基准的报表开发(ireport)

    javabean完成以后就是添加ireport的报表了 打开ireport的option然后在classpath中添加路径. 然后在ireport中追加数据源如图,点击图标后会出现数据源列表然后按ne ...

  7. 数据挖掘算法(一)C4.5

    统计了14天的气象数据D(指标包括outlook,temperature,humidity,windy),并已知这些天气是否打球(play).如果给出新一天的气象指标数据:sunny,cool,hig ...

  8. android 单元测试

    android studio 2.0创建一个空android moudle后, 会出现两个test目录,其中一个是Instrument Test, 另一个则是Unit Test Unit Test 和 ...

  9. liunx ln -s 软连接

    项目中遇到不同项目中上传图片共享问题 解决方法就用到了 liunx的ln -s 的软连接, 用法: liunx ln -s 文件路径 实现共享思路:不同的目录都软连接到同一个目录

  10. 【Fiddler】改写返回数据功能

    方法一:打断点 1.在手机上设置好代理后,随便进入一个APP:之后选择Rules->Automatic Breakpoints->After Responses,在返回值处打断点 2.重新 ...