可信网站认证 代理商,怎样建网站买东西,PHP是做网站最好的,汝州市城乡建设局网站目录 1. 如何实现分布式锁
2. Redis 分布式锁存在什么问题
2.1 解决死锁问题
2.2 解决锁误删问题 1. 如何实现分布式锁
Redis 天生就可以作为一个分布式系统来使用#xff0c;所以它实现的锁都是分布式锁。 Redis 可以通过 setnx#xff08;set if not exists#xff09…目录 1. 如何实现分布式锁
2. Redis 分布式锁存在什么问题
2.1 解决死锁问题
2.2 解决锁误删问题 1. 如何实现分布式锁
Redis 天生就可以作为一个分布式系统来使用所以它实现的锁都是分布式锁。 Redis 可以通过 setnxset if not exists命令实现分布式锁~
setnx mylock true - 加锁del mylock - 释放锁 通过执行结果是否为 1 可以判断是否成功获取到锁~ 2. Redis 分布式锁存在什么问题
Redis 分布式锁存在两个问题
1.死锁问题未设置过期时间锁忘记释放加锁后还没来的及释放锁就宕机了都会导致死锁问题.
2. 锁误删问题设置了超时时间但是线程执行超过超时时间后锁误删问题.
2.1 解决死锁问题 MySQL 中解决死锁问题是通过设置超时时间Redis 也是如此但是问题来了第一步先加锁然后再设置超时时间那么就不满足原子性了那么怎么办 ? 官方在 Redis 2.6.12 版本之后新增了一个功能我们可以使用一条命令既执行加锁操作又设置超时时间setnx 和 expire 第一条命令成功加锁并设置 30 s 过期时间第二条命令跟在第一条命令后还没有超过 30s所以获取失败
2.2 解决锁误删问题
锁误删问题是解决死锁问题带来的问题如何理解 既然知道了什么是锁误删问题那么如何解决
答可以通过添加锁标识来解决. 前面我们使用 set 命令的时候只使用到了 key那么可以给 value 设置一个标识表示当前锁归属于那个线程例如 valuethread1,valuethread2.....
但是这样解决依然存在问题因为新增锁标识之后线程在释放锁的时候需要执行两步操作了
判断锁是否属于自己如果是就删除锁
这样就不能保证原子性了那该怎么办
【解决方案】
使用 lua 脚本来解决 Redis 本身就能保证 lua 脚本里面所有命令都是原子性操作使用 Redisson 框架来解决主流
那么 Redisson 如何实现分布式锁呢
【代码示例】
1.引入 Redisson 依赖
dependencygroupIdorg.redisson/groupIdartifactIdredisson-spring-boot-starter/artifactIdversion3.23.2/version
/dependency
2.创建 RedissonClient 对象
Configuration
public class RedissonConfig {Beanpublic RedissonClient redissonClient() {Config config new Config();config.useSingleServer().setAddress(redis://127.0.0.1:6379);// 如果有密码需要设置密码return Redisson.create(config);}
}3.调用分布式锁
RestController
public class LockController {Resourceprivate RedissonClient redissonClient;RequestMapping(/lock)public String lockResource() throws InterruptedException {String lockKey myLock;// 获取锁RLock lock redissonClient.getLock(lockKey);try {// 超时时间 10s, [tryLock 获取成功才需要释放锁,获取失败不需要释放锁]boolean isLocked lock.tryLock(20, TimeUnit.SECONDS);if(isLocked) {// 成功获取到锁try {TimeUnit.SECONDS.sleep(5);return 成功获取到锁并执行业务代码;} catch (InterruptedException e) {e.printStackTrace();} finally {// 释放锁lock.unlock();}} else {// 获取锁失败return 获取锁失败;}} catch (InterruptedException e) {e.printStackTrace();}return 获取锁成功;}
}启动项目使用 8080 端口访问接口