redis之分布式锁

CSDN云计算公众号
以下文章来源于水滴与银弹 ,作者Magic Kaito

核心问题:

在这里插入图片描述

为什么要使用分布式锁?

再开始讲分布式锁之前,有必要简单介绍一下,为什么需要分布式锁?

与分布式锁相对应的是【单机锁】,我们在写多线程程序的时候,避免同时操作一个共享变量产生数据问题,通常会使用一把锁来【互斥】,以保证共享变量的正确性,其使用范围是【同一进程】中。

如果换做是多个线程,需要同时操作一个共享资源,如何互斥呢?

例如,现在的业务应用通常都是微服务架构,这也意味着一个应用会部署多个进程,那这多个进程如果需要修改MySql中的同一行记录时,为了避免操作乱序倒置数据错误,此时,我们就需要引入【分布式锁】来解决问题了。

想要实现分布式锁,必须借助一个外部系统,所有进程都去这个系统申请【加锁】,而这个外部系统,必须要实现【互斥】的能力,即两个请求同时进来,只会给一个进程返回成功,另一个返回失败(或等待),这个外部系统,可以是MySql,也可以是Redis或者Zookeeper,但为了追求更好的性能,我们通常会选择Redis或Zookeeper来做。

分布式锁如何实现?

我们从最简单的开始讲起。
想要实现分布式锁,必须要求Redis有【互斥】的能力,我们可以使用SETNX命令,这个命令表示SET IF NOT EXISTS
,即如果key不存在,才会设置它的值,否则什么都不做。

两个客户端进程可以执行这个命令,达到互斥,就可以实现一个分布式锁,

客户端1申请加锁,加锁成功:

127.0.0.1:6379> SETNX lock 1
(integer) 1 //客户端1,加锁成功

客户端2申请加锁,因为它后到达,加锁失败:

127.0.0.1:6379> SETNX lock 1
(integer) 0 //客户端2,加锁失败

此时,加锁成功的客户端;就可以去操作【共享资源】,例如,修改MYSQL的某一行数据,或者调用一个API请求。
操作完成后,还要及时的释放锁,给后来者让出操作共享资源的机会,如何释放锁呢?
直接使用DEL命令删除这个KEY即可:

127.0.0.1:6379> DEL lock 
(integer) 1 

但是,它存在一个很大的问题,当客户端1拿到锁之后,如果发生下面的场景,就会造成【死锁】:

1、程序处理业务逻辑异常,没有及时释放锁
2、进程挂了,没机会释放锁

这时,这个客户端就会一直占用这个锁,而其他的客户端就【永远】拿不到这把锁了。

怎么解决这个问题呢?

如何避免死锁?

我们很容易想到的方案就是,在申请锁的时候,就给设置一个【租期】。
在Redis中实现时,就是给 这个KEY设置一个【过期时间】。这里我们假设,操作共享资源的时间不超过10S,那么在给这个key设置10S过期即可:

127.0.0.1:6379> SETNX lock 1
(integer) 1 
127.0.0.1:6379> EXPIRE lock 10
(integer) 1 

这样一来,无论客户端是否异常,这个锁都可以在10S后【自动释放】,其他客户端依旧可以拿到锁。
但这样真的就没有问题吗?
还是有问题。
现在的操作,加锁,设置过期时间是2条命令,有没有可能只执行了第一条,第二条却【来不及】执行的情况发生呢?例如:
1、SETNX执行成功,执行EXPIRE时由于网络问题,执行失败。
2、SETNX执行成功,Redis异常宕机,Expire没有机会执行。
3、SETNX执行成功,客户端异常奔溃,Expire没有机会执行。

总之,这两条命令不能保证是原子操作(一起成功),就有潜在的风险倒置过期时间设置失败,那就依旧会发生【死锁】问题。

怎么办?

在Redis 2.6.12 之后,Redis扩展了Set命令的参数,用下面这一条命令就可以了:

127.0.0.1:6379> SET lock 1 EX 10 NX
OK

这就解决了死锁问题,也比较简单。
我们再来分析下,它还有什么问题?

试想这样一种场景:
1、客户端1加锁成功,开始操作共享资源
2、客户端1操作共享资源的时间,

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值