深入剖析Java之redis分布式锁实现

本文深入探讨了在分布式系统中使用Redis实现分布式锁的方法,包括满足的条件、应用场景、利用Redis的setNX命令实现原理及解决死锁的策略。通过代码实现展示了如何在Java中有效使用Redis分布式锁,同时讨论了相关的问题,如为何不直接使用expire超时和避免并发获取锁的情况。
摘要由CSDN通过智能技术生成

一、使用分布式锁要满足的几个条件:

系统是一个分布式系统(关键是分布式,单机的可以使用ReentrantLock或者synchronized代码块来实现)
共享资源(各个系统访问同一个资源,资源的载体可能是传统关系型数据库或者NoSQL)
同步访问(即有很多个进程同事访问同一个共享资源。没有同步访问,谁管你资源竞争不竞争)

二、应用的场景例子

管理后台的部署架构(多台tomcat服务器+redis【多台tomcat服务器访问一台redis】+mysql【多台tomcat服务器访问一台服务器上的mysql】)就满足使用分布式锁的条件。多台服务器要访问redis全局缓存的资源,如果不使用分布式锁就会出现问题。 看如下伪代码:

long N=0L;
//N从redis获取值
if(N<5){
N++;
//N写回redis
}

上面的代码主要实现的功能:

从redis获取值N,对数值N进行边界检查,自加1,然后N写回redis中。 这种应用场景很常见,像秒杀,全局递增ID、IP访问限制等。以IP访问限制来说,恶意攻击者可能发起无限次访问,并发量比较大,分布式环境下对N的边界检查就不可靠,因为从redis读的N可能已经是脏数据。传统的加锁的做法(如java的synchronized和Lock)也没用,因为这是分布式环境,这个同步问题的救火队员也束手无策。在这危急存亡之秋,分布式锁终于有用武之地了。

分布式锁可以基于很多种方式实现,比如zookeeper、redis…。不管哪种方式,他的基本原理是不变的:用一个状态值表示锁,对锁的占用和释放通过状态值来标识。

这里主要讲如何用redis实现分布式锁。

三、使用redis的setNX命令实现分布式锁

1、实现的原理

Redis为单进程单线程模式,采用队列模式将并发访问变成串行访问,且多客户端对Redis的连接并不存在竞争关系。redis的SETNX命令可以方便的实现分布式锁。

2、基本命令解析

1)setNX(SET if Not eXists)

语法:

SETNX key value
将 key 的值设为 value ,当且仅当 key 不存在。

若给定的 key 已经存在,则 SETNX 不做任何动作。

SETNX 是『SET if Not eXists』(如果不存在,则 SET)的简写

返回值:

设置成功,返回 1 。
  设置失败,返回 0 。
例子:


redis> EXISTS job                # job 不存在
(integer) 0

redis> SETNX job "programmer"    # job 设置成功
(integer) 1

redis> SETNX job "code-farmer"   # 尝试覆盖 job ,失败
(integer) 0

redis> GET job                   # 没有被覆盖
"programmer"

所以我们使用执行下面的命令

SETNX lock.foo <current Unix time + lock timeout + 1>
如返回1,则该客户端获得锁,把lock.foo的键值设置为时间值表示该键已被锁定,该客户端最后可以通过DEL lock.foo来释放该锁。

如返回0,表明该锁已被其他客户端取得,这时我们可以先返回或进行重试等对方完成或等待锁超时。

2)getSET

语法:

GETSET key value
  将给定 key 的值设为 value ,并返回 key 的旧值(old value)。

当 key 存在但不是字符串类型时,返回一个错误。

返回值:

返回给定 key 的旧值。
  当 key 没有旧值时,也即是, key 不存在时,返回 nil 。
3)get
语法:
GET key
返回值:

当 key 不存在时,返回 nil ,否则,返回 key 的值。
  如果 key 不是字符串类型,那么返回一个错误

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值