bug消消乐分布式面试精选

(面试高频)分布式锁

2021-03-24  本文已影响0人  zzj0990

什么是锁

普通的锁,即在单机多线程环境下,当多个线程需要访问同一个变量或代码片段时,被访问的变量或代码片段叫做临界区域,我们需要控制线程一个一个的顺序执行,否则会出现并发问题。
如何控制呢?就是设置一个各个线程都能看的见的标志。然后,每个线程想访问临界区域时,都要先查看标志,如果标志没有被占用,则说明目前没有线程在访问临界区域。如果标志被占用了,则说明目前有线程正在访问临界区域,则当前线程需要等待。
这个标志,就是
在单机多线程的java程序中,我们可以使用堆内存中的变量作为标志,因为多线程是共享堆内存的,堆内存中的变量对于各个线程都是可见的。

分布式锁

在分布式环境下,即多台计算机,每个计算机上会启动jvm执行程序的运行环境下,如果不同计算机上的线程想访问临界区域时,该怎么办呢?
前面普通锁的使用堆内存中的变量的方式肯定不适用了。因为在多机环境下,某台计算机上的堆内存中的变量对于其他计算机上的线程肯定是不可见的。那么,根据锁的本质和原理,我们就要找到另外的对于多机上的线程都可见的标志,以它来作为锁,就可以了。这样的锁,就是分布式锁。
当然,这里只是解释了什么是分布式锁,至于分布式锁该如何实现,其实有多重方式,关键在于要保证锁对多机上的程序是可见的即可。

分布式锁应该具备哪些条件?

1. 在分布式系统环境下,一个方法在同一时间只能被一个机器的一个线程执行;
2. 高可用的获取锁与释放锁;
3. 高性能的获取锁与释放锁;
4. 具备可重入特性;
5. 具备锁失效机制,防止死锁;
6、具备非阻塞锁特性,即没有获取到锁将直接返回获取锁失败。

场景描述

现实生活中一种常见的场景,抢票。抢票系统一般为适应高并发性,会将服务部署多套(以承载瞬间的大并发场景),分布式锁控制不好,往往会出现超买情况。

那么我们分以下三种方案来分析分布式锁的设计:

1. 数据库乐观锁

2. Redis

2.1. setnx
直接利用setnx,执行完业务逻辑后调用del释放锁,简单粗暴
缺点:如果setnx成功,还没来得及释放,服务挂了,那么这个key永远都不会被获取到,从而造成死锁

2.2. setnx设置一个过期时间
为了改正2.1。的缺陷,我们用setnx获取锁,然后用expire对其设置一个过期时间,如果服务挂了,到了过期时间自动释放
缺点:
①setnx和expire是两个方法,不能保证原子性,如果在setnx之后,还没来得及expire,服务挂了,还是会出现锁不释放的问题;
②还会导致当前的线程释放其他线程占有的锁;

2.3. set k v ex tm nx
redis官方为了解决2.2.存在的缺点,在v2.8版本为set指令添加了扩展参数nx和ex,保证了setnx+expire的原子性,使用方法:
set key value ex 5 nx
缺点:
①如果在过期时间内,事务还没有执行完,锁提前被自动释放,其他的线程还是可以拿到锁,出现超卖;
可以通过看门狗,定时续时长来解决

2.4. 加一个事务id
对于2.2.中的第二个缺点,可以理解为当前线程有可能会释放其他线程的锁,那么问题就转换为保证线程只能释放当前线程持有的锁,即setnx的时候将value设为任务的唯一id,释放的时候先get key比较一下value是否与当前的id相同,是则释放,否则抛异常回滚
缺点:get key和将value与id比较是两个步骤,不能保证原子性

2.5. Redis集群(主从)
会出现系统刚获得分布式锁,此时主Redis宕机(数据还未同步到从节点),也会出现超卖,一次Redis的创始人提出了RedLock算法。

2.6. RedLock
这个场景是假设有一个 redis cluster,有 5 个 redis master 实例(一定是奇数个,他们之间无主从关系,都是相互独立的)。然后执行如下步骤获取一把锁:

a. 获取当前时间戳,单位是毫秒;
b. 轮流尝试在每个 master 节点上创建锁,过期时间较短,一般就几十毫秒;
c. 尝试在大多数节点上建立一个锁,比如 5 个节点就要求是 3 个节点` n / 2 + 1`;
d. 客户端计算建立好锁的时间,如果建立锁的时间小于超时时间,就算建立成功了(设置一个请求过期时间re和锁的过期时间le,同时re必须小于le);
e. 要是锁建立失败了,那么就依次之前建立过的锁删除;
f. 只要别人建立了一把分布式锁,你就得不断轮询去尝试获取锁。

缺点:RedLock原图链接

RedLock.png

3. ZooKeeper

总结

没有绝对完美的实现方式,具体要选择哪一种分布式锁,需要结合每一种锁的优缺点和业务特点而定。
忘记在哪里看到过一句话:过度追求设计完美,是一种心理疾病

参考

上一篇 下一篇

猜你喜欢

热点阅读