redis分布式锁

yanhe言和 / 2023-05-03 / 原文

加锁

1 判断锁是否被占用,没有则获取锁(hset/hincrby)并设置过期时间(expire)

2 如果锁被占用,则判断是否是当前线程占用,如果是获取锁(hset/hincrby)并设置过期时间(expire)

3 否则获取锁失败

 if redis.call('exists',KEYS[1])==0 or redis.call('hexists',KEYS[1],ARGV[1]) ==1 
 then     
     redis.call('hincrby',KEYS[1],ARGV[1],1)     
     redis.call('expire',KEYS[1],ARGV[2])
     return 1 
 else     
     return 0 
 end

 

释放锁

1 判断自己的锁是否存在(hexists),不存在返回nil

2 如果存在则减1(hincrby-1),判断减1后是否为0 ,为0则del,并返回1

3 如果不为0,则返回0

 if redis.call('hexists',KEYS[1],ARGV[1])==0
 then
     return nil
 elseif redis.call('hincrby',KEYS[1],ARGV[1],-1)==0
 then
     return redis.call('del',KEYS[1])
 else
     return 0
 end

 

续期

判断自己的锁是否存在hexists,如果存在则重置过期时间

 if redis.call('hexists',KEYS[1],ARGV[1])==1
 then 
 return redis.call('expire',KEYS[1],ARGV[2])
 else
 return 0
 end

 

redis 测试脚本
加锁
eval "if redis.call('exists',KEYS[1])==0 or redis.call('hexists',KEYS[1],ARGV[1]) ==1  then          redis.call('hincrby',KEYS[1],ARGV[1],1)          redis.call('expire',KEYS[1],ARGV[2])     return 1  else          return 0  end" 1 lock 1234567890 30
释放锁
eval "if redis.call('hexists',KEYS[1],ARGV[1])==0 then     return nil elseif redis.call('hincrby',KEYS[1],ARGV[1],-1)==0 then     return redis.call('del',KEYS[1]) else     return 0 end" 1 lock 1234567891
续期
eval "if redis.call('hexists',KEYS[1],ARGV[1])==1 then return redis.call('expire',KEYS[1],ARGV[2]) else return 0 end" 1 lock 1234567890 30