redission 分佈鎖
redission 分佈鎖使用了map 這種數據結構,key爲鎖的名稱,map的key客戶端,value爲重入的個數
代碼進行分析,大致代碼都寫到RedissionLock這個類裏。
加鎖:
//判斷該鎖是否存在,如果該鎖不存在
if (redis.call('exists', KEYS[1]) == 0)
向map類型中添加數據, key爲客戶端id ,value 爲 1 ,表示當前鎖重入的個數爲1
then redis.call('hset', KEYS[1], ARGV[2], 1);
設置過期時間 ,默認爲30秒
redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end;
//如果存在該鎖,並且該鎖的持有者和當前客戶端id相同
if (redis.call('hexists', KEYS[1], ARGV[2]) == 1)
//將重入的個數加 1
then redis.call('hincrby', KEYS[1], ARGV[2], 1);
redis.call('pexpire', KEYS[1], ARGV[1]);
返回0
return nil; end;
//上述都不符合的話,就返回該key的過期時間
return redis.call('pttl', KEYS[1]);
key1 是要加鎖的key
argv1 鎖的key默認生存時間
argv2 加鎖的客戶端id,爲生成的 UUID + thread_id ,UUID會在redission客戶端對象創建的時候生成
釋放鎖:
0代表釋放失敗,1代表釋放成功
//如果鎖不存在
if (redis.call('exists', KEYS[1]) == 0)
//發送釋放鎖的消息,返回1
then redis.call('publish', KEYS[2], ARGV[1]); return 1; end;
//如果持有該鎖的客戶端id 不是當前id ,釋放鎖失敗
if (redis.call('hexists', KEYS[1], ARGV[3]) == 0) then return nil;end;
//如果鎖的持有者和當前客戶端id一致,將可重如個數-1
local counter = redis.call('hincrby', KEYS[1], ARGV[3], -1);
//如果當前可重入鎖的個數大於0,說明鎖不可以被釋放
if (counter > 0) then redis.call('pexpire', KEYS[1], ARGV[2]); return 0;
//如果當前可重入鎖的個數爲0,說明鎖可以被釋放
else redis.call('del', KEYS[1]); redis.call('publish', KEYS[2], ARGV[1]); return 1; end;
//否則返回null
return nil;
詳細信息可以查看 分佈式鎖
zookepper 實現分佈鎖: