乐趣区

关于java:如何使用Redis实现分布式锁

首先来说 Redis 作为一个独立的三方零碎,其天生的劣势就是能够作为一个分布式系统来应用,因而应用 Redis 实现的锁都是分布式锁,了解了这个概念才能看懂本文所说的内容。

分布式锁的示意图,如下所示:

分布式锁实现

应用 Redis 实现分布式锁,能够 通过 setnx(set if not exists)命令实现 ,当咱们应用 setnx 创立键值胜利时,则表明加锁胜利,否则既代码加锁失败。因为 Redis 主线程是单线程运行的,所以也不会有同时加锁胜利的状况。
实现命令如下:

127.0.0.1:6379> setnx lock true
(integer) 1 #创立锁胜利
#逻辑业务解决...
127.0.0.1:6379> del lock
(integer) 1 #开释锁

当咱们反复加锁时执行后果如下:

127.0.0.1:6379> setnx lock true # 第一次加锁
(integer) 1
127.0.0.1:6379> setnx lock true # 第二次加锁
(integer) 0

从上述命令中能够看出,咱们能够应用执行的后果是否为 1 来判断加锁是否胜利。

散布锁问题

然而,应用 setnx 实现散布锁有一个【死锁问题】,就是当加锁的线程(或利用)掉电或解体之后,其余线程只能有限期待上来的问题。

此时,咱们 解决死锁问题能够通过增加设置锁的过期工夫来实现
也就是 setnx 和 expire 配合应用,在 Redis 2.6.12 版本之后,新增了一个弱小的性能,咱们能够应用一个原子操作也就是一条命令来执行 setnx 和 expire 操作了,实现命令如下:

127.0.0.1:6379> set lock true ex 30 nx
OK #创立锁胜利
127.0.0.1:6379> set lock true ex 30 nx
(nil) #在锁被占用的时候,希图获取锁失败

其中 ex 为设置超时工夫,nx 为元素非空判断,用来判断是否能失常应用锁的。

小结

Redis 作为一个独立的三方零碎,其劣势是天生能够实现分布式锁。它实现分布式锁是通过 setnx 来实现的,然而只有 nx(not exists)可能会产生死锁的问题,所以咱们最终实现死锁应该应用 set nx ex 的形式来实现。

小思考:当设置了过期工夫之后,Redis 实现分布式仍然会有一个小小的问题,有人晓得这个问题和解决方案吗?欢送评论区写出你的答案。
此文章点赞过 100,我会给出标准答案。

本文已收录到我的面试小站 www.javacn.site,其中蕴含的内容有:Redis、JVM、并发、并发、MySQL、Spring、Spring MVC、Spring Boot、Spring Cloud、MyBatis、设计模式、音讯队列等模块。

退出移动版