Redis-分布式锁

1.系统是一个分布式系统
2.共享资源(各个系统访问同一个资源,资源的载体可能是传统关系)
3. 同步访问(即有很多个进程同时访问同一个共享资源)

什么是分布式锁?

**线程锁:**主要用来给方法、代码块加锁。当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或该代码段。线程锁只在同一JVM中有效果,因为线程锁的实现在根本上是依靠线程之间共享内存实现的,比如synchronized是共享对象头,显示锁Lock是共享某个变量(state)。

**进程锁:**为了控制同一操作系统中多个进程访问某个共享资源,因为进程具有独立性,各个进程无法访问其他进程的资源,因此无法通过synchronized等线程锁实现进程锁。

**分布式锁:**当多个进程不在同一个系统中,用分布式锁控制多个进程对资源的访问。

分布式锁应用场景

虽然线程和进程间的并发问题都可以用分布式锁来解决,但是分布式锁解决这些小问题是非常消耗资源的。分布式锁应该用来解决分布式情况下的多进程并发问题。

实现分布式锁

实现的原理
Redis为单进程单线程模式,采用队列模式将并发访问变成串行访问,且多客户端对Redis的连接并
不存在竞争关系。redis的SETNX命令可以方便的实现分布式锁。
基本命令解析
1)setNX(SET if Not eXists)
语法:
SETNX key value

将 key 的值设为 value ,当且仅当 key 不存在。
若给定的 key 已经存在,则 SETNX 不做任何动作。
SETNX 是『SET if Not eXists』(如果不存在,则 SET)的简写
返回值:
设置成功,返回 1 。
设置失败,返回 0 。

为分布式锁设定时间
SETNX lock.foo <current Unix time + lock timeout + 1>
如果 SETNX返回 1 ,说明客户端已经获得了锁,SETNX将键 lock.foo 的值设置为锁的超时时间(当前时间 + 锁的有效时间)。 之后客户端可以通过DEL lock.foo 来释放锁。
如果 SETNX返回 0 ,说明 key 已经被其他客户端上锁了。如果锁是非阻塞(non blocking lock)的,我们可以选择返回调用,或者进入一个重试循环,直到成功获得锁或重试超时(timeout)。

2)getSET
先获取key对应的value值。若不存在则返回nil,然后将旧的value更新为新的value。
语法:
GETSET key value
将给定 key 的值设为 value ,并返回 key 的旧值(old value)。
当 key 存在但不是字符串类型时,返回一个错误。
返回值:
返回给定 key 的旧值[之前的值]。
当 key 没有旧值时,也即是, key 不存在时,返回 nil 。
注意的关键点:
1、同一时刻只能有一个进程获取到锁。setnx
2、释放锁:锁信息必须是会过期超时的,不能让一个线程长期占有一个锁而导致死锁;
(最简单的方式就是del, 如果在删除之前死锁了。)

死锁

死锁情况是在判断超时后,直接操作业务,设置过期时间,执行业务,然后删除释放锁。其他进程再次通过setnx来抢锁。
解决死锁
如果当一个持有锁的客户端失败或崩溃了不能释放锁,该怎么解决?
可以通过锁的键对应的时间戳来判断这种情况是否发生了,如果当前的时间已经大于lock.foo的值,说明该锁已失效,可以被重新使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值