分布式锁:
分布式锁是控制分布式系统或者不同系统之间共同访问资源的一种锁实现,如果不同的系统或同一个系统的不同主机之间共享了某个资源,往往需要互斥来防止彼此干扰来保证一致性。
需解决问题:
1.任意时刻,只能用一个客户端获取锁,不能同时有两个客户端获取到锁
2.锁只能被持有改锁的客户端删除,不能由其他客户端删除
3.死锁:获取锁的客户端因为某些原因而未能释放锁,其他客户端再也无法获取到该锁
4.容错:当部分节点(redis节点等)down机时,客户端仍能够获取锁和释放锁
redis 分布式锁解决问题:
(1)互斥性:redis的命令可以保证只有一个客户端可以写入成功,其他客户端会写入失败。
(2)安全性:设置key的value时,通过构造全局唯一的 my_random_value,在删除锁时key和value都相等时才可以进行删除,以此来保证本客户端的锁不会被其他客户端删除。
(3)死锁:由于一些异常情况(比如:服务器重启)使得锁没有释放,这样会导致死锁,通过设置redis的key过期时间,来避免这种异常死锁。
(4)容错:当redis主节点down机时,redis从节点晋升为主节点,继续提供分布式锁服务。
原理流程图:
Spring boot 流程:
1.添加pom
Redisson 就是用于在 Java 程序中操作 Redis 的库,它使得我们可以在程序中轻松地使用 Redis。Redisson 在 java.util 中常用接口的基础上,为我们提供了一系列具有分布式特性的工具类。
2.添加工具类
Redisson工具类RedissonClient
@Lazy:注解注解的作用主要是减少springIOC容器启动的加载时间
当出现循环依赖时,也可以添加@Lazy
@Component:把普通pojo实例化到spring容器中,相当于配置文件中的<bean id="" class=""/>
3.使用
@Autowired
private RedisLock redisLock;
@Autowired 注释,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作
RLock lock = redisLock.lock("out_point:" + outProjectId );
"out_print":自定义标识符
outProjectId:用于筛选唯一值
lock.lock();
添加锁:Lock()对象执行了锁定操作,其他的线程都必须等这个线程完成,并释放锁之后,才能执行被锁住的代码块
lock.unlock();
释放锁:unlock(),放于finally()中执行代码块
设置过期时间:
到达过期时间时,自动回收释放锁。
Redis
它是线程安全的,我们利用它的特性可以很轻松的实现一个分布式锁,如 opsForValue().setIfAbsent(key,value)
它的作用就是如果缓存中没有当前 Key 则进行缓存同时返回 true
反之亦然;当缓存后给 key 在设置个过期时间,防止因为系统崩溃而导致锁迟迟不释放形成死锁; 那么我们是不是可以这样认为当返回 true
我们认为它获取到锁了,在锁未释放的时候我们进行异常的抛出….