使用lua实现redis分布式锁
Lua官网
http://doc.redisfans.com/script/eval.html
问题重现:预约功能,用jemter测试,30个不同用户同时预约,2个用户重复发送请求,即重复发送消息场景,结果导致重复消费
避免重复消费方式
1.如第6行,重复原因:第10行,业务逻辑耗时比较长,还没执行第11行,导致6行,执行通过,重复的数据都进来了
2.如第5行+12行,高并发下,加分布式锁,重复请求(具体场景是什么),只有一个能执行业务逻辑。这样不够,6行还是要保留,保证幂等。
分析:分布式锁只能保证高并发下幂等行,无法保证持久幂等。这里注意:分布式锁与existKey,都不是一个固定值,保证10业务逻辑可以并发执行。
高并发与幂等行没有关系。
1 String key = RedisEnum.APPOINT_RECORD_KEY.toKey(reqVO.getLiveId(), reqVO.getUid()); 2 String uniqueVal = UUID.randomUUID().toString(); 3 String lockKey = RedisEnum.APPOINT_RECORD_LOCK_KEY.toKey(reqVO.getLiveId(), reqVO.getUid()); 4 try { 5 if (redisManager.tryLock(lockKey, uniqueVal, APPOINT_RECORD_LOCK_KEY.expired)) {6 Boolean exist = redisManager.existsKey(key);7 if (Boolean.TRUE.equals(exist)) {8 log.error("saveAppoint exception already appointed reqParam:{}", JSON.toJSONString(reqVO));9 throw ExceptionUtils.throwException(LIVE_APPOINTED);} 10 todo 处理业务逻辑 11 redisManager.put(key, RedisEnum.APPOINT_RECORD_KEY.expired, JSON.toJSONString(reqVO));} } catch (Exception e) {log.error("Saving appoint exception", e);throw ExceptionUtils.throwException(LIVE_APPOINTED); } finally {12 redisManager.releaseLock(lockKey, uniqueVal); } return false;
参考:
https://blog.csdn.net/qq_39736103/article/details/116452752?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-0&spm=1001.2101.3001.4242
lua实现
加锁:
public boolean tryLock(String lockKey, String randomUnValue, int expireTime) {Jedis jedis = null;boolean var6;try {jedis = this.jedisPool.getResource();Long result = (Long)jedis.eval(LuaSecript.SETNX_AND_EXPIRE.getScript(), 1, new String[]{lockKey, randomUnValue, String.valueOf(expireTime)});if (result != 1L) {return false;}var6 = true;} catch (Exception var10) {this.logger.error("Try lock failed", var10);return false;} finally {if (jedis != null) {jedis.close();}}return var6;}
public enum LuaSecript {SETNX_AND_EXPIRE("local is_existed = redis.call('setnx', KEYS[1], ARGV[1]);if (is_existed == 1) then redis.call('expire', KEYS[1], ARGV[2]);return 1; end; return 0;"),DEL_KEY_AND_EQUAL_VAL("if (redis.call('get', KEYS[1]) == ARGV[1]) then return redis.call('del', KEYS[1]);else return 0;end; "),ZRANGEBYSCORE_ZREM("local data = redis.call('ZRANGEBYSCORE', KEYS[1], ARGV[1], ARGV[2], 'WITHSCORES', 'LIMIT', ARGV[3], ARGV[4]);if table.getn(data) > 0 then for k,v in pairs(data) do if (k % 2) ~=0 then redis.call('ZREM', KEYS[1], v);end;end;return data;end;");private String script;private LuaSecript(String script) {this.script = script;}public String getScript() {return this.script;}
}
解锁:
public boolean releaseLock(String lockKey, String randomUnValue) {Jedis jedis = null;boolean var5;try {jedis = this.jedisPool.getResource();jedis.eval(LuaSecript.DEL_KEY_AND_EQUAL_VAL.getScript(), 1, new String[]{lockKey, randomUnValue});return true;} catch (Exception var9) {this.logger.error("Release lock failed", var9);var5 = false;} finally {if (jedis != null) {jedis.close();}}return var5;}
依赖
<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId></dependency>
使用lua实现redis分布式锁相关推荐
- 【代码学习】lua+redis分布式锁代码实现实例
文章目录 分布式锁场景和介绍: 分布式锁模板类: 锁实现类 lua脚本加锁和解锁 分布式速度限制 测试分布式锁 分布式锁场景和介绍: 分布式锁演进-基本原理 分布式锁演进-阶段一 分布式锁演进-阶段二 ...
- Redis分布式锁—SETNX+Lua脚本实现篇
前言 平时的工作中,由于生产环境中的项目是需要部署在多台服务器中的,所以经常会面临解决分布式场景下数据一致性的问题,那么就需要引入分布式锁来解决这一问题. 针对分布式锁的实现,目前比较常用的就如下几种 ...
- 使用redis分布式锁+lua脚本实现分布式定时任务控制demo
2019独角兽企业重金招聘Python工程师标准>>> 分布式系统经常要遇到定时任务执行的问题,不能重复执行,但很多时候又不能统一到一个微服务里面,因为这样就失去了微服务的意义.由于 ...
- 基于 Redis + Lua 脚本实现分布式锁,确保操作的原子性
为了保证数据的争用安全,通常要采用锁机制控制. 如果是单应用部署,直接通过synchronized关键字修改方法,就能解决,但是如果是分布式的部署 该方法就不能解决这个问题啦,此时就引出了一个分布式锁 ...
- Redis分布式锁使用不当,酿成一个重大事故,超卖了100瓶飞天茅台!!!
点击关注公众号,Java干货及时送达 来源:juejin.cn/post/6854573212831842311 基于Redis使用分布式锁在当今已经不是什么新鲜事了. 本篇文章主要是基于我们实际项目 ...
- Redis 分布式锁使用不当,酿成一个重大事故,超卖了100瓶飞天茅台!!!
点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 基于Redis使用分布式锁在当今已经不是什么新鲜事了. 本 ...
- 秒杀商品超卖事故:Redis分布式锁请慎用!
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:浪漫先生 来源:juejin.im/post/6854573 ...
- 记一次由Redis分布式锁造成的重大事故,避免以后踩坑!
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:浪漫先生 juejin.im/post/5f159cd8f2 ...
- Redis 分布式锁没这么简单,网上大多数都有 bug
Redis 分布式锁这个话题似乎烂大街了,不管你是面试还是工作,随处可见,「码哥」为啥还写? 因为看过很多文章没有将分布式锁的各种问题讲明白,所以准备写一篇,也当做自己的学习总结. 在进入正文之前,我 ...
- 深度剖析:Redis分布式锁到底安全吗?看完这篇文章彻底懂了!
阅读本文大约需要 20 分钟. 大家好,我是 Kaito. 这篇文章我想和你聊一聊,关于 Redis 分布式锁的「安全性」问题. Redis 分布式锁的话题,很多文章已经写烂了 ...
最新文章
- OpenCV+python:膨胀和腐蚀
- 删除空值_空白单元格行,如何快速批量删除?简单方法,效率飞升
- 智能停车O2O 独角兽初现:“ETCP停车”获5000万美金A轮融资
- 使用Python进行汽车黑客攻击:泄露GPS和OBDIICAN总线数据
- 运用div css和java_如何将css应用于div模式
- python爬虫JS逆向加密破解之百度翻译
- Gym102028G Shortest Paths on Random Forests 生成函数、多项式Exp
- Mybatis的缓存
- js 监听浏览器刷新操作
- vue-property-decorator
- linux中的 bin sh,Linux-#!/bin/sh理解
- 第一次作业补充:项目调研
- 《赐我》-一只白羊 同步歌词
- 计算机怎样将多行文字转换成表格,怎么把表格里的字变成两行
- 海报与Banner的区别
- 解决APP抓包问题【网络安全】
- 用Python机器人监听微信群聊 !
- 小远qq1611532647淘宝主图设计
- 自动控制原理3.2---一阶系统的时域分析
- linux apache fcgi,Apache使用fcgi方式与PHP结合