标签:断网 机器 方案 ali 应该 strong try 就是 red
为了防止分布式系统中的多个进程之间相互干扰,我们需要一种分布式协调技术来对这些进程调度,而这种分布式协调技术的核心就是分布式锁。
分布式锁实现的三个核心要素:加锁、解锁、锁超时。
(1)加锁
以双11秒杀商品为例讨论。小明对商品A进行购买操作,此时小明会使用 setnx(prodId,threadId) 命令,来对商品加锁。若此时执行命令之后返回 1 ,则说明小明加锁成功。小红在同一时间做相同操作,返回 0 ,则说明小红加锁失败。
(2)解锁
小明购买完商品之后要立即释放锁,提供给包括小红在内的其他购买者使用,小明此时执行del(prodId)命令,将锁释放。
(3)锁超时
如果小明在购买的过程中,突然网断了,获取了锁,但是没有释放锁,那之后的购买者只有等待。所以为了解决这种 死锁 的问题,小明在加锁时,必须执行 expire(prodId,30) 给锁设置一个超时时间,来保证即使没有显示的释放锁,这把锁在一定时间之后也能自动释放。
伪代码如下:
if(setnx(prodId,threadId) == 1){ expire(prodId,30) try { do something ...... } finally { del(prodId) } }
4.以上伪代码中存在三个致命问题
(1) setnx 和 expire 的非原子性
setnx 与 expire 是分两步进行操作的,如果执行完setnx操作之后,还没执行 expire 命令设置超时时间,网络断掉,此时造成死锁。
出现这个问题的根本原因在于setnx与expire是分两步进行的,如果这两个操作时原子性的,将很好的避免这种问题,所以redis提供了解决方案:在加锁的同时,设置超时时间。
set(prodId,threadId,30)
(2) 误删操作
小明在购买商品加锁时设置的锁超时时间时30s,但是30s之后小明仍然没有购买完成,此时redis自动释放锁,小红获得了锁,在小红购物的过程中,小明购买完成,需要删除锁,误将小红的锁删除。
为了避免这个问题,在加锁时,小明需要将自己的线程Id当作参数传进去。
String threadId = Thread.currentThread().getId() set(key,threadId ,30)
在解锁时先判断是不是自己的锁,如果是自己的锁,再进行删除锁的操作。
if(threadId .equals(redisClient.get(key))){ del(key) }
(3)同一时间两个线程访问同一资源
上述情况会出现同一时间两个线程访问同一资源的情况。为了尽量避免这种情况,我们可以给获得锁的线程去开启一个守护进程,当到达超时时间时,如果还没有进行完自己的操作,守护进程,给该进程加部分时间,当该线程处理完自己的任务之后,会显示的关闭掉守护进程。如果没有处理完成,断网了,守护进程会自动终止,到达超时时间时,该线程就将锁释放了。
(1)四种Zonde节点
默认的节点类型。创建节点的客户端与Zookeeper断开连接之后,该节点依旧存在。
在创建节点时,zookeeper会根据创建的时间将节点进行排序。
和持久节点想相反。当创建节点的客户端与zookeeper断开连接之后,临时节点会被删除。
当创建节点时,zookeeper会根据节点的创建时间的先后顺序进行排序,当创建节点的客户端与Zookeeper断开连接之后,临时节点会被删除。
(2)zookeeper 分布式锁原理
zookeeper实现分布式锁就是应用了临时顺序节点,具体流程如下:
① 100名客户在极短的时间内去访问商品服务,进行购买商品的操作。
② 获取锁
zookeeper创建100个临时顺序节点,这些节点按照请求的先后顺序进行排序。排名第一的 req1 优先获取锁,排名第二 req2 的向只比他靠前一名的 req1 注册Watcher,排名第三的 req3 向 req2 注册Watcher,依次类推。
③ 释放锁
?正常执行完释放锁
当 req1 执行完成之后,zookeper会删除该节点,排名第二的 req2 获得锁,依次类推。
?客户端崩溃释放锁
当排名第一的用户在购买时断网,因为zookeeper为其创建的是临时顺序节点,此时排名第一的用户获得的锁也将释放。排名第二的用户获得锁。
6.redis与zookeeper的分布式锁比较
分布式锁 | 优点 | 缺点 |
zookeeper |
1.有封装好的框架,容易实现 2.有等待锁的队列,大大提高抢锁效率
|
添加和删除节点性能较低 |
redis | set与del命令性能高 | 实现复杂,没有等待队列,容易出现羊群效应 |
标签:断网 机器 方案 ali 应该 strong try 就是 red
原文地址:https://www.cnblogs.com/zhouzhile/p/11197958.html