通常情况在解决分布式场景锁机制都会首先想到redis。因为redis单线程天然就解决了这个问题。使用redis实现分布式锁可以通过getset和setnx。
redis> GETSET db mongodb # 没有旧值,返回 nil
(nil)
redis> GET db
"mongodb"
redis> GETSET db redis # 返回旧值 mongodb
"mongodb"
redis> GET db
"redis"
redis> EXISTS job # job 不存在
(integer) 0
redis> SETNX job "programmer" # job 设置成功
(integer) 1
redis> SETNX job "code-farmer" # 尝试覆盖 job ,失败
(integer) 0
redis> GET job # 没有被覆盖
"programmer"
然而这个方式在锁等待的情况下,都无法主动获取锁释放通知,必须轮询的方式去不断的查redis。这个就会产生大量查询请求并且会增加等待时间(譬如你10ms轮询一次,但是可能下一毫秒已经可以获得锁了,你却需要继续等10ms)。接下来我分享一段我基于redis SUBPUB机制实现的分布式锁的思路:
附: 1. eventId结构:固定位数节点ID+13位时间戳+唯一序列
public String buildEvenId(){
return new StringBuilder().append(EVENT_ID_PREFIX).append(System.currentTimeMillis()).append(eventIdSeq.incrementAndGet()).toString();
}