分布式锁的应用场景
当多个机器(多个进程)会对同一条数据进行修改时,并且要求这个修改是原子性的。这里有两个限定:
- 多个进程之间的竞争,意味着JDK自带的锁失效;
- 原子性修改,意味着数据是有状态的,修改前后有依赖。
分布式锁的实现条件:
- 高性能(加、解锁时高性能)
- 可以使用阻塞锁与非阻塞锁。
- 不能出现死锁。
- 可用性(不能出现节点 down 掉后加锁失败)。
Redis使用分布式锁
本文将先介绍Redis的实现方式,当然Redis实现分布式锁有多种方案,本文介绍一种基于lua脚本的实现方案。后面笔者会介绍分布式锁的其他实现(基于 DB 的唯一索引和基于 ZK 的临时有序节点)。
本方案中Redis的实现主要基于setnx 和给予一个超时时间(防止释放锁失败)。
多个尝试获取锁的客户端使用同一个key做为目标数据的唯一键,value为锁的期望超时时间点;
首先进行一次setnx命令,尝试获取锁,如果获取成功,则设置锁的最终超时时间(以防在当前进程获取锁后奔溃导致锁无法释放)
这里利用 Redis set key 时的一个 NX 参数可以保证在这个 key 不存在的情况下写入成功。并且再加上 EX 参数可以让该 key 在超时之后自动删除。
注意:此处使用Jedis的如下方法,该命令可以保证 NX EX 的原子性。
一定不要把两个命令(NX EX)分开执行