Redis的典型应用:分布式锁

什么是分布式锁?

在一个分布式系统中,会涉及到多个节点访问同一个公共资源的情况,此时就需要通过锁来做互斥控制,避免出现类似于线程安全的问题。

但java中的synchronized或者c++的std::mutex这样的锁都只能在当前进程中生效,在分布式这种多个进程多个主机的场景下就无能为力了,所以此时就需要用到分布式锁~

本质上就是使用一个公共的服务器,来记录加锁状态

分布式锁的基础实现

本质上是通过一个键值对来标识锁的状态:

考虑买票的场景, 现在⻋站提供了若⼲个⻋次, 每个⻋次的票数都是固定的. 现在存在多个服务器节点, 都可能需要处理这个买票的逻辑 : 先查询指定⻋次的余票, 如果余票 > 0, 则设 置余票值 -= 1。
可以在上述架构中引入一个Redis作为分布式锁的管理器。
此时, 如果 买票服务器1 尝试买票, 就需要先访问 Redis, 在 Redis 上设置⼀个键值对. ⽐如 key 就是⻋次, value 随便设置个值 (⽐如 1). 如果这个操作设置成功, 就视为当前没有节点对该 001 ⻋次加锁, 就可以进⾏数据库的读写操作. 操作完成之后, 再把 Redis 上刚才的这个键值对给删除掉.
如果在 买票服务器1 操作数据库的过程中, 买票服务器2 也想买票, 也会尝试给 Redis 上写⼀个键值对, key 同样是⻋次. 但是此时设置的时候发现该⻋次的 key 已经存在了, 则认为已经有其他服务器正在持有锁, 此时 服务器2 就需要等待或者暂时放弃

引入过期时间

上述方案,当服务器1加锁之后,开始处理买票的过程中,如果服务器1意外宕机了,没法进行解锁操作,就会导致其他服务器始终无法获取到锁的情况。

所以为了解决这个问题,可以在设置key的时候引入过期时间,这样这个锁持有一定时间后就会被释放。

注意:严格来讲,redis是不具备原子性的,引入过期时间的操作最好使用一个命令,如果分开设置锁跟过期时间,即便使用事务也不能保证这两个操作都一定成功。

引入校验id

对于redis中写入的加锁键值对,其他节点是可以删除的,比如服务器1写入一个01:1这样的键值对,服务器2是可以把这个键值对删除掉的,虽然服务器2不会恶意删除,但不能保证因为一些bug导致服务器2把锁误删的情况。

为了解决上述问题,我们可以引入一个校验id:

比如可以把设置的键值对的值,不单单设置成1,而是设成服务器的编号,如“001”:“服务器”.这样就可以在删除key的时候,先校验当前删除的key的服务器是不是当初加锁的服务器,是才删除,不是就不能删除。

引入watch dog

虽然我们设置了key过期时间之后,但仍然存在当任务没执行完,key就先过期了,导致锁提前失效。

这个时候就需要一个单独的线程(watch dog),通过这个线程对锁过期时间进行续约:

加入过期时间为10s,同时设定看门狗线程每隔3s检测一次,那么3s之后,看门狗就会判断当前任务是否完成,如果完成,则直接通过lua脚本的方式释放锁;如果没完成,则把过期时间重写设置为10s。

引入Redlock算法

实践中其实还会出现一种很大怨种的情况:

服务器1 向 master 节点进⾏加锁操作. 这个写⼊ key 的过程刚刚完成, master 挂了; slave 节
点升级成了新的 master 节点. 但是由于刚才写⼊的这个 key 尚未来得及同步给 slave 呢, 此时 就相当于 服务器1 的加锁操作形同虚设了, 服务器2 仍然可以进⾏加锁 (即给新的 master 写⼊ key. 因为新的 master 不包含刚才的 key).

 

我们引⼊⼀组 Redis 节点. 其中每⼀组 Redis 节点都包含⼀个主节点和若⼲从节点. 并且组和组之间存 储的数据都是⼀致的, 相互之间是 "备份" 关系(⽽并⾮是数据集合的⼀部分, 这点有别于 Redis cluster). 加锁的时候, 按照⼀定的顺序, 写多个 master 节点. 在写锁的时候需要设定操作的 "超时时间". ⽐如50ms. 即如果 setnx 操作超过了 50ms 还没有成功, 就视为加锁失败。
简单来说就是如果给某个节点加锁失败,就立即尝试下一个节点,当加锁成功的节点数超过总节点数的一半,才视为加锁成功,这样的话,即便某些节点挂了,也不影响所得正确性~~
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值