Redisson分布式锁使用
- Redisson分布式锁使用 推荐度:
- 相关推荐
Redisson分布式锁使用
一、使用 RedisTemplate 操作分布式锁
原子加锁(uuid Value+过期时间)+原子解锁(lua脚本)+加长过期时间
- UUID :让锁区分,防止错删其他锁
- 设置锁过期时间:当业务异常导致无法释放锁形成锁死,设置过期时间自动释放锁
- Lua脚本:能够保证删除操作的原子性
- 加长过期时间:过期时间必须大于业务执行时间
1.加锁 (set key)try{2.业务:向redis缓存存入数据(1)查redis缓存数据,缓存有直接返回,(2)缓存没查到直接查数据库,(3)在锁释放之前 放入redis缓存}catch{处理异常}finally{3.释放锁 (delete key)}
public Map<String, List<CategoryLevel2Vo>> getCatelogJsonFromDataWithRedisLock() {//set NX key不存在才能set//设置set lock hah EX 300 NX,设置过期时间EX,防止死锁,加锁跟设置过期时间必须是原子性操作String uuid = UUID.randomUUID().toString();Boolean lock = stringRedisTemplate.opsForValue().setIfAbsent("lock", uuid,300,TimeUnit.SECONDS);//lock为true set成功if (lock){System.out.println("获取分布式锁成功");//加锁成功Map<String, List<CategoryLevel2Vo>> dataFromDb;try {dataFromDb = getDataFromDb();} finally {//释放锁(删除lock)//使用lua删除锁脚本,或者值+比较值+删除锁(脚本可以保证原子性)String redisScript = "if redis.call(\"get\",KEYS[1]) == ARGV[1] then return redis.call(\"del\",KEYS[1]) else return 0 end";Long execute = stringRedisTemplate.execute(new DefaultRedisScript<Long>(redisScript, Long.class), Arrays.asList("lock"), uuid);}return dataFromDb;}else {//加锁失败System.out.println("获取分布式锁失败,等待重试");//休眠try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}//自旋return getCatelogJsonFromDataWithRedisLock();}
二、Lock锁
为什么Lock锁不用循环判断是否拿到锁?
lock是阻塞锁,拿不到锁不会执行
Lock锁与RedisTemplate 操作分布式锁区别,Redisson与Redis锁的区别?
- 自动续期,lock.lock()加锁时,看门狗LockWatchdogTimeout定时更新过期时间
- 防止死锁,当业务异常导致无法释放锁,看门狗默认30s释放锁
1.加锁 lock.lock() 或 lock.lock(10, TimeUnit.SECONDS);
try{2.业务...
}catch{处理异常
}finally{3.释放锁 lock.unlock();
}
1.lock.lock(); 有续期
如果业务未完成,则锁自动续期,看门狗LockWatchdogTimeout默认时间30s,续期按
如果业务完成,则不会续期,如果不手动释放锁,默认30s后释放
如果占锁,则开启定时任务,重新设置过期时间(LockWatchdogTimeout),定时任务:使用掉三分之一的LockWatchdogTimeout就恢复成 30s
2.lock.lock(10, TimeUnit.SECONDS); 无续期,推荐使用
注意:设置锁时间必须大于业务执行时间,否则业务结束之前释放锁会被其他线程占锁,当业务结束释放时,删除了其他线程的锁
没有看门狗LockWatchdogTimeout
锁时间结束不会自动续期,设置锁时间大于业务执行时间
占锁成功,如果出现事故导致无法释放锁,在不抛出异常的情况下,会默认30s后释放锁,所以不会存在死锁的问题
锁的名字,粒度越细越好 product-11-lock、product-12-lock
public Map<String, List<CategoryLevel2Vo>> getCatelogJsonFromRedissonLock() {//锁的名字,粒度越细越好 product-11-lock、product-12-lockRLock lock = redissonClient.getLock("CatelogJson-lock");//加锁成功lock.lock();Map<String, List<CategoryLevel2Vo>> dataFromDb = null;try {dataFromDb = getDataFromDb();} catch (Exception e) {e.printStackTrace();} finally {//释放锁lock.unlock();}return dataFromDb;}
最新文章
- php调用接口及编写接口
- Driller源码阅读笔记(二)
- snmp是什么?
- Application.platform 平台
- 网络安全和黑客技能:15本必读书籍推荐
- gridview的ButtonField
- 什么是LRUCache 和 LRUCache 实现
- 强力删除各种文件夹
- 聊聊职场
- VSS的使用方法
- EXT2和3区别
- JAVA关于Calendar类的使用
- 欧几里得距离和曼哈顿距离
- 机器学习并没有那么深奥,它很有趣(2)
- HTML5通过js调用手机摄像头
- cefsharp内嵌资源html的读取,C#(csharp)用CefSharp开发实现一个浏览器,抓取网站任意资源...
- pip执行指令后报语法错误sys.stderr.write(f”ERROR: {exc}”)解决办法