一、集群下的线程并发安全问题:
通过加锁可以解决在单机情况下的一人一单安全问题,但是在集群模式下就不行了。
==》原因:
在集群模式下,有多个JVM就会有多个锁监视器,每个JVM内部可以监视到线程实现互斥,每个JVM内部都会有一个线程是成功的,如果集群模式下,部署多台的话,就会有并行的多个线程成功运行,就会出现线程安全问题

二、分布式锁:
(一)、概念:
分布式锁:满足分布式系统或集群模式下多进程可见并且互斥的锁。

(二)、分布式锁的实现:
分布式锁的核心是实现多进程之间互斥,而满足这一点的方式有很多,常见的有三种:

(三)、基于Redis实现分布式锁:
实现分布式锁时需要实现的两个基本方法:
1、释放锁:
==》可能会遇到的情况:
当还未释放锁的时候,服务宕机了。那么就没办法释放锁,后面的线程就进不来。所以通常会设置一个超时时间,在服务宕机后,到一定时间锁就会自动释放了。

2、获取锁:
==》可能遇到的情况:
当执行完获取锁的动作后NX,还未来得及设置过期时间EX,服务就宕机了。还是会导致线程无法执行。

所以通常把NX和EX变成一个原子操作(同时成功,同时失败)

==》在redis中获取锁失败后有两种机制:阻塞机制和非阻塞机制。阻塞机制就是如果获取锁失败后,会继续尝试等待锁释放;非阻塞机制是如果获取锁失败后,就直接返回结果,不再等待锁释放。
3、业务流程:
这里采用非阻塞方式。

4、基于Redis实现分布式锁--初级版本
==》VoucherOrderServiceImpl:
(四)、分布式锁误删问题:
1、问题一描述:
当线程1获取锁后开始执行业务,在这期间发生业务阻塞,导致超过了给锁设置的超时时间,导致锁自动释放了。然后线程2进来了,获取锁后开始执行业务,在线程2执行业务的期间,线程1的业务完成了,然后就去释放锁,直接把线程2的锁给释放了。释放完锁后,线程3又获取锁,开始执行业务............

2、解决:
在释放锁的时候判断一下是不是自己的锁。

3、问题二描述:
当判断完锁的唯一标识后,正准备释放锁,此时又发生了阻塞(JVM的垃圾回收机制)超过了给锁设置的超时时间...产生了误删锁的问题

4、解决:
使得判断锁的唯一标识和释放锁 为一个原子操作:
4.1、Redis的Lua脚本:
Redis提供了Lua脚本功能,在一个脚本中编写多条Redis命令,确保多条命令执行时的原子性。Lua是一种编程语言, 参考语法


4.2、基于Lua脚本实现分布式锁的释放锁逻辑:


3、代码实现:

unlock.lua:
SimpleRedisLock:
3、总结:

三、分布式锁Redisson:
(一)、引入:

(二)、Redission的概念
Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式服务,其中就包含了各种分布式锁的实现

官网地址: https://redisson.org GitHub地址: https://github.com/redisson/redisson
(三)、Redission入门:

1、可重入锁:
可重入锁指的是同一个线程可无限次地进入同一把锁的不同代码,又因该锁通过线程独占共享资源的方式确保并发安全,又称为独占锁。
==》举例:比如对于同一个线程而言,有方法1调用了方法2尝试去获取锁,在方法2里又尝试去获取锁,一个线程两次去获得锁,这就是重入。

===》而对于之前的业务,如下图,每次获取锁使用后就释放掉,所以对于同一个线程而言,如果连续两次获取锁,获取到的不会是同一把锁
String类型:

1.1、Redisson实现可重入锁原理:
每次获取锁时都会判断下标识,如果是自己的锁,就把锁的个数加1,然后释放锁的时候还会判断下是否是自己的标识,如果是的话,再判断下锁的个数,如果值为0了,就代表该线程所有的业务都执行完了,就会释放锁。如果值不为0,由于进来的个数和出去的个数相等,那么就代表,还有业务没有执行完,就不会把锁释放掉。
hash类型:

2、Redisson实现主从一致性原理:
2.1、主从一致性问题:
主节点会进行数据同步给从节点。只有主节点可以读写。当一个锁的标识存入主节点后,还未来得及同步给从节点,此时主节点发生了故障,然后就会从任一从节点选择一个作为主节点,但是但是锁的标识还未同步,就会锁不生效,然后发生并发安全问题

2.2、multiLock:
不设置主从节点,而是一个个独立的Redis节点,必须依次向多个Redis节点获取锁,每个Redis都获取了锁,并且保存了锁的唯一标识才算获取锁成功。因为没有主从,就不会有主从一致性问题。如果想让可用性更好,可以在每个redis后面再加几个Redis从节点,即使这里有主从结构也不会有并发安全问题,因为当某个主节点发生故障后,从节点会变成主节点,但并没有获取到锁的标识。前面说过,只有每一个节点都拿到锁才能成功,所有最终也会失败。

9402

被折叠的 条评论
为什么被折叠?



