javaDEMO
Java 基础 Demo 站: https://www.javastudy.cloud
Java 中高级开发博客: https://www.lixiang.red
Java 学习公众号: java 技术大本营
分布式锁总述
如果我们应用 A 部署了两台,然后这两台都为数据 D 做了缓存, 在某一时刻,两个机器都发现缓存失效了,这时候是两台机器都去请求数据库吗? 肯定不是,只能有一台机器去请求, 这时候分布式锁就派上用场了.
网上有很多网址都有提及到,分布式锁主要有三种实现方式,其本质核心就是先找到一个中间层,在中间层来决定哪个机器去访问
一. 在 Redis 中去创建同一个 key
二.在 Zookeeper 中去创建同一个 Node
三.在 Mysql 中创建一个唯一索引的数据行
本 DEMO 主要是介绍使用 Redis 去做分布式锁
Redis 做分布式锁
如上段所述,redis 做分面式锁主要是在 Redis 中去创建同一个 key,因此还是 set 命令的变形,set 命令参考文档:
https://redis.io/commands/set
网上大都是 setnx,但从文档中,我们可以看到,从 redis 2.6.12 之后,官方推荐直接使用 set 命令来实现
Starting with Redis 2.6.12 SET supports a set of options that modify its behavior:
EX
seconds -- Set the specified expire time, in seconds.PX
milliseconds -- Set the specified expire time, in milliseconds.NX
-- Only set the key if it does not already exist.
Note: Since the SET command options can replace SETNX, SETEX, PSETEX, it is possible that in future versions of Redis these three commands will be deprecated and finally removed.
如上,redis 中分布式锁可用 set lock:javastudy 1 ex 3 nx
来操作,如成功,则执行逻辑,然后删掉锁,或执行逻辑中有问题,则等锁自动过期
springboot 中使用 Redis 做分布式锁
首先是在 springboot 中使用 redis,参考文章:https://www.javastudy.cloud/articles/2019/11/04/1572845689729.html
DEMO 级别的
通过 RedisTemplate
实现上述 set 命令的 DEMO 代码如下:
@Autowired
private RedisTemplate<String, Object> redisTemplate;
public boolean setNx(String key, Object value, long timeout) {
return redisTemplate.opsForValue().setIfAbsent(key, value, timeout, TimeUnit.SECONDS);
}
进阶的
做为 DEMO 级别,以上代码以够用,但是在生产中,如应用 A 先获取到了锁,但是锁了 10 秒,自己又在处理的过程中出了问题,没能删掉锁, 那后面的应用就 G 了,所以后面的应用 B 在没有获取到锁的时候,要先获取下这个 key 的创建时间,如果和当前时间的差别太大,B 就强制删掉这个锁
参考代码如下:
private boolean getLock(String lockKey,long expire, int count) {
if (redisService.setNx(lockKey, DateUtils.currentTimeMillis(), expire)) {
return true;
} else {
// 获取锁的创建时间
long createTime = (long) redisService.get(lockKey);
// 这里的比较可以在expire基础上乘一个自定义的小数
if ((DateUtils.currentTimeMillis() - createTime) > (expire)) {
count++;
// 最大尝试次数
if (count > MAX_RETRY_COUNT) {
return false;
}
redisService.del(lockKey);
// 使用递归再尝试去获取锁
getLock(lockKey,expire, count);
}
return false;
}
}
DEMO 总评
分布式锁,redis 做分布式锁这一块在面试中几乎是必问,不仅仅要做到对原理了解,更要写法熟练,本 DEMO 代码的工具方法可以直接拷贝使用,其中一些可扩展的点可以自行配置,更多的还是要根据业务场景来做选择技术方案,加油!
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于