分布式锁: 甲乙两人购买时剩余量都显示一个,如果同时下单可能会出现问题,这时就需要用到分布式锁
分布式锁是实现有序调度不同的进程,解决不同进程之间相互干扰的问题的技术手段
分布式锁的应具备的条件
在分布式系统环境下,分布式锁在同一个时间仅能被同一个进程访问
高可用的获取/释放锁
高性能的获取/释放锁
具备锁的重入性
具备锁的失效机制,防止死锁
具备非阻塞锁的特性,即使没有获取锁也能直接返回结果
分布式锁的实现有哪些
mechache:
利用mechache的add命令,改命令是原子性的操作,只有在key 不存在的情况下,才能add成功,也就意味着线程拿到了锁
Redis:
和Mechache的实现方法相似,利用redis的setnx命令,此命令同样是原子性的操作,只有在key不存在的情况下,add成功
zookeeper:
利用他的顺序临时节点,来实现分布式锁和等待队列,zookeeper的设计初衷就是为了实现分布式微服务的
使用Redis实现分布式锁的思路
先去redis中使用setnx(商品id,数量) 得到返回结果
这里的数量无所谓,它的作用就是告诉其他服务,我加上了锁
发现redis中有数量,说明已经可以加锁了
发现redis中没有数据,说明已经获得到了锁
解锁: 使用redis的 del商品id
锁超时, 设置exprie 生命周期,如30秒, 到了指定时间,自定解锁
三个致命问题
非原子性操作:setnx,宕机,expire
因为 setnx和expire不是原子性的,要么都成功要么都失败, 一旦出现了上面的情况,就会导致死锁出现
redis提供了原子性的操作 set ( key , value , expire)
误删锁
假如我们的锁的生命事件是30秒,结果我在30s内没操作完,但是锁被释放了
jvm2拿到了锁进行操作
jvm1 操作完成使用del,结果把jvm2 的锁删除了
解决方法, 在删除之前,判断是不是自己的锁
redis提供了原子性的操作 set ( key ,threadId, expire)
超时为完成任务
增加一个守护线程,当快要超时,但是任务还没执行完成,就增加锁的时间