分布式锁
2020-10-18 23:45:14 10 举报
redis分布式锁
作者其他创作
大纲/内容
解决:
解决:在del释放锁之前先判断一下是不是自己加2的锁,至于具体实现,可以在加锁的时候把当前线程ID当作value, 并在删除之前验证key对应的value是不是自己的线程ID
String threadId = Thread.currentThread().getId()set(key,threadId ,30,NX)
加锁
Zookeeper:利用Zook的顺序临时结点,来实现分布式锁和等待队列。Zookeeper设计的初衷,就是为了实现分布式锁服务
为什么使用分布式锁?
分布式锁的实现有哪些
通过redis分布式锁的实现来理解基本概念
if(threadId .equals(redisClient.get(key))){ del(key)}
在分布式系统环境下,一个方法在同一时间只能被一个机器的一个线程执行
分布式锁实现的三个核心要素:
解锁
线程A获取到锁,但是执行慢,超过了过期时间,这时候第二个线程B获取到了该锁,但是此时线程A执行完成后,删除了该锁(此时删除的是线程B加的锁)
使用set命令,里面增加了可选参数
我们虽然避免了误删key的情况,但是同一时间会有多个线程访问代码块,仍是不完美的
分布式锁应该具备的条件
具备锁失效机制,防止死锁
分布式锁
即便结点忽然断掉,由于线程和守护线程在同一个进程内,守护线程也会停掉。这把锁超时的时候,无人续命,也就自动释放了
解锁:
存在问题
最简单的方式就是使用del命令
高性能的获取与释放锁
功能:为了防止分布式系统中的多个进程之间相互干扰
if(setnx(lock_sale_商品ID,1) == 1){ expire(lock_sale_商品ID,30) try { do something ...... } finally { del(lock_sale_商品ID) }}
Chubby:Google公司实现的粗粒度分布式锁服务,底层利用了Paxos一致性算法
高可用的获取锁与释放锁
线程执行setnx返回值
具备可重入特性(重新进入,由多于一个任务并发使用,而不必担心数据错误)
导致setnx成功后,还没来得及expire,结点就挂掉了,这样一来,就变成了死锁
最简单的办法就是使用setnx命令
为题三:判断和释放锁是两个独立的操作,不是原子性
当当前线程执行完任务的时候,会显示的关掉守护线程
问题一:setnx和expire的非原子性
key是锁的唯一标识,按业务来决定命名
防止一个得到锁的线程在执行任务的过程中挂掉,来不及显式地释放锁,这块资源将会永远被锁住(死锁),其他线程也不能进入
使用守护线程,给快要过期的锁进行续航
加锁:
value的设置,在这里暂且不考虑,后面会用到
实现
具备非阻塞锁特性,即:没有获取到锁直接返回获取失败
比如锁的过期时间是30,则守护线程从第29秒开始执行,每20秒执行一次
1:说明key原本不存在,该线程成功获取到了锁
锁超时
因为现实生活中,有这样的例子,在不同的服务器上存在着相同的一个变量,而又有多个客户端同时发来请求想要对这个变量操作,显然结果是不对的。即使不是同时发过来,多个请求分别操作不同的内存区域的数据,变量之间不存在共享,也不具有可见性,处理的结果也是不对的。
作用:
Memcached:利用他的add命令。次命令是原子操作,只有在key不存在的情况下,才能add成功,也就意味着线程得到了锁
0:说明key原本已存在,该线程抢锁失败
问题二:del导致误删
Redis:利用Redis的setnx命令。此命令是原子操作,只有key不存在的情况下,才能set成功
代码:
0 条评论
下一页