引子
redis作为一个强大的key/value数据库。事实上还能够用来实现轻量级的分布式锁。
1.实现方案1
最早官方在命令页给了一个实现:
acquire lock: SETNX lock.foo
release lock: DEL lock.foo
acquire lock when time expired: GETSET lock.foo
只是这个方法有漏洞。就是release lock用的DEL命令不支持cas删除(delete if current value equals old value)。这样忽略race condition将会出现故障:
A client will try to release the lock after the expire time deleting the key created by another client that acquired the lock later.
2.实现方案2
官方在命令页介绍了新的方案:SET command + Lua script:
Starting with Redis 2.6.12 it is possible to create a much simpler locking primitive using the command to acquire the lock, and a simple Lua script to release the lock. The pattern is documented in the command page.
The old based pattern is documented below for historical reasons.
该方案有2个优化:
(1)SET 命令能够设置key过期时间:SET key value [EX seconds] [PX milliseconds] [NX|XX]
The lock will be auto-released after the expire time is reached.
(2)使用Lua脚本实现cas删除(详见命令页)
It is possible to make this system more robust modifying the unlock schema as follows:
- Instead of setting a fixed string, set a non-guessable large random string, called token.
- Instead of releasing the lock with , send a script that only removes the key if the value matches.