redis实现分布式锁
2018-06-18 03:13:25来源:未知 阅读 ()
清理邮件的时候发现之前看的一篇关于redis分布式锁实现的文章有人回复- -当时随意扫了眼文章,为了防止发生死锁,思路是使用setnx设置value为本地时间,然后获取锁失败时读取value进行时间比对。。然后我回复了下。。多台应用服务器存在时间不同步的问题。。
其实使用setnx时设置下redis过期时间简单方便,只是通常在应用程序内通过sdk做这项操作时由于赋值+设置过期不在同一原子性操作中。。所以很多人觉得不可行了。。那就直接使用lua脚本呗,简单方便,原子性操作,性能也OK。
加锁:aquire_lock_with_timeout.lua
if redis.call("exists",KEYS[1]) == 0 then local lockSrc = redis.call("setex",KEYS[1],unpack(ARGV)) if lockSrc then return "1" end return "0" end return "-1"
释放锁:release_lock.lua
if redis.call("get",KEYS[1]) == ARGV[1] then local lockRelease = redis.call("del",KEYS[1]) if lockRelease then return "1" end return "0" end return "-1"
java为例,加载两个lua脚本,然后简单加锁,释放锁
@Bean @Qualifier("lockScript") public RedisScript<Integer> acquireLockWithTimeout() { DefaultRedisScript redisScript = new DefaultRedisScript(); redisScript.setLocation(new ClassPathResource("redis/acquire_lock_with_timeout.lua")); redisScript.setResultType(Integer.class); return redisScript; } @Bean @Qualifier("unLockScript") public RedisScript<Integer> releaseLock() { DefaultRedisScript redisScript = new DefaultRedisScript(); redisScript.setLocation(new ClassPathResource("redis/release_lock.lua")); redisScript.setResultType(Integer.class); return redisScript; }
private Integer acquireTimeout;//资源占有锁的时间 秒s private Integer acquireInterval;//尝试获取锁的时限 ms private Integer lockTime;//尝试获取锁的时间间隔 ms @Autowired private RedisTemplate redisTemplate; @Autowired @Qualifier("lockScript") private RedisScript<Integer> acquireLockWithTimeout; @Autowired @Qualifier("unLockScript") private RedisScript<Integer> releaseLock; public String tryLock(String lockKey) { String lockValue = UUID.randomUUID().toString(); Long endTime = System.currentTimeMillis() + acquireTimeout; while (System.currentTimeMillis() < endTime) { Integer lockResult = (Integer) redisTemplate.execute(acquireLockWithTimeout, Collections.singletonList(lockKey), lockTime, lockValue); if (lockResult.equals(1)) { return lockValue; } else { try { Thread.sleep(acquireInterval); } catch (InterruptedException ex) { continue; } } } return ""; } public boolean releaseLock(String lockKey, String lockValue) { Integer releaseResult = (Integer) redisTemplate.execute(releaseLock, Collections.singletonList(lockKey), lockValue); if (releaseResult.equals(1)) { return true; } return false; }
当然java也有更复杂更丰富的组件 redisson
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- redis缓存 2020-06-12
- DES/3DES/AES 三种对称加密算法实现 2020-06-11
- Spring Boot 2.3.0 新特性Redis 拓扑动态感应 2020-06-11
- 聊聊微服务架构及分布式事务解决方案! 2020-06-10
- SpringBoot + Vue + ElementUI 实现后台管理系统模板 -- 后 2020-06-10
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash