1. 业务场景
经常在需要防止重复调用的业务逻辑中(例如秒杀、防止重复消费等逻辑)使用分布式锁,使用redis实现时常见的实现方式。平时只是使用,但是并没有专门总结,今天来做下总结。
2. redis实现
先使用docker开启一个redis实例
1 2 3 4 5 6
|
$ docker run -d -p 6379:6379 --name my-redis \ -v /mydata/redis/data:/data \ -v /mydata/redis/conf/redis.conf:/etc/redis/redis.conf \ --restart=always --network common-network redis:latest \ redis-server /etc/redis/redis.conf
|
进入redis内部
1
| $ docker exec -it my-redis redis-cli
|
a. 使用 setnx + expire
1 2 3 4 5 6 7 8 9
| 127.0.0.1:6379> setnx test_key dummy OK
127.0.0.1:6379> expire test_key 100 (integer) 1
127.0.0.1:6379> setnx test_key aa (integer) 0
|
缺点:setnx和expire不是原子操作,如果setnx后还没有expire操作,redis挂了,这个锁将没法过期了,影响业务。
b. 使用set 扩展命令
命令如下
1 2
| 127.0.0.1:6379> set key value [NX|XX] [GET] [EX seconds|PX milliseconds|EXAT unix-time-seconds|PXAT unix-time-milliseconds|KEEPTTL]
|
例如可以通过以下命令设置
1 2
| 127.0.0.1:6379> set test_key dummy NX EX 100
|
c. 使用Lua脚本实现
1 2 3 4 5
| if redis.call('setnx',KEYS[1],ARGV[1]) == 1 then redis.call('expire',KEYS[1],ARGV[2]) else return 0 end;
|
redis中
3. Java实现