Redis分布式锁 命令 注意: 这篇博客系本人将以前在OneNote的笔记搬到CSDN ,由于OneNote操作的特殊性 会存在很多截图便于说明只用。 不喜勿喷。
特点 支持分布式 可以更细粒度的控制 多台机器上多个进程对一个数据进行操作的互斥 应用场景 将 用户下单减库存这个动作 必须要单线程操作。 这个形参 key 可以是 商品id 第35行的判断是 根据key获取到的value 如果小于当前时间。 第34行的判断是 根据key获取到的value 如果是空值 第 34和35 行就是 锁过期了 如果锁过期 就获取上一个锁的事件 并比较 总结 简化版 redis 分布式锁 就是一个setnx 动作 简化版redis 锁的缺点 如果 获取锁成功 但是后面的 下单 减库存等操作失败抛出异常(偶发), 这样会导致 解锁操作 没法进行,因为已经抛出异常了。 这个时候 已经加锁但是无法解锁,下次一个新请求过来,setnx 是会失败的。 这样 就造成死锁发生,下图的逻辑 就永远停留在这一步加锁这一步但是永远失败 进化版 redis锁 在上上图简化版redis锁的 基础上 增加了 第31到40行的操作。 因为setnx设置了过期时间,31行得到 lockA 。 在 第33到34行 判断 锁是否过期,(lockA 为空或则小于当前时间), 如果 锁过期 就会进入 36行 比较 上一个锁的日期 就有机会返回true 从而得到锁 并有机会释放锁。 在多线程 情况下 讨论 如果多线程 进入到上图 27行 (假设两个线程) 两个线程 都会进行判断,假设锁都被占用,所以他们不会进入28行,直接进入31行,因为锁已经被一个线程占用了, 这个时候 假设,那个拿到锁的线程 的 currentValue 值是A ,而两个线程的 value 值是B。 如果 那个拿到锁的线程 的锁超时,就会进入下图 36行。 这个36行 采用了 getset 方法,这个value 的值是B (这个36行的 getset只会有一个线程去执行原子性) , 假设是第一个线程去执行,拿到的 oldValue值是A 这个currentValue 值也是 A ,如果判断相等就会返回true 。这个时候就是第一个线程拿到了锁。 接着 第二个线程又去执行这个 36行的代码,拿到的 oldValue值是B 这个currentValue 值也是 A ,就不相等 就拿不到锁。 结果就是多线程情况下 只有一个线程恩给你拿到锁。 解锁操作 运用 redis锁的 方式 加锁 这个 Timeout 是 一个超时时间,用static 和final 修饰 成员变量 注意 这个setnx 的key 是商品id 是属于细粒度的操作 从第 62行到 65行 解锁 就 第85行的操作 分布式锁 流程图
|
|
来自: 不忘初心g2x5dp > 《大数据》