1. 程式人生 > 資料庫 >Redis分散式鎖

Redis分散式鎖

應用場景

當多個應用程序(客戶端)需要互斥地訪問共享資源時,可以使用分散式鎖。其中Redis官方權威提出了RedLock。Java中可使用Redssion提供的實現。

注意點:

  1. 互斥,保證任何時刻只能有一個客戶端 獲取到鎖;
  2. 效率之死鎖,保證獲取到鎖的客戶端即使在出現網路分割槽或者宕機的情況下,也能釋放掉鎖;
  3. 效率之容錯,保證只要大多數Redis節點正常工作,客戶端就能正常獲取到鎖和正常釋放鎖。

原理:
獲取鎖:

SET resource_name my_random_value NX [EX|PX] 30000

Redssion中的實現使用了Hash,可重入:

if (redis.call(‘exists’,KEYS[1]) == 0)

then redis.call(‘hset’,KEYS[1],ARGV[2],1);
redis.call(‘pexpire’,ARGV[1]);
return nil;
end;
if (redis.call(‘hexists’,ARGV[2]) == 1)
then redis.call(‘hincrby’,1);
redis.call(‘pexpire’,ARGV[1]);
return nil;
end;
return redis.call(‘pttl’,KEYS[1]);

釋放鎖:

if redis.call(“get”,KEYS[1]) == ARGV[1] then
return redis.call(“del”,KEYS[1])

else
return 0
end

Redisson的釋放鎖實現:

if (redis.call(‘hexists’,ARGV[3]) == 0)
then return nil;
end;
local counter = redis.call(‘hincrby’,ARGV[3],
-1);
if (counter > 0)
then redis.call(‘pexpire’,ARGV[2]);
return 0;
else redis.call(‘del’,KEYS[1]);
redis.call(‘publish’,KEYS[2],ARGV[1]);

return 1;
end;
return nil;

Redis分佈鎖常見的幾種實現方案:

  1. 單機
    缺點:單點故障,整個服務無法使用。

  2. 主從複製
    缺點:failover問題。 根本原因在於主從複製有延遲。當master在slave複製成功前宕機,slave晉升為master時沒有宕機時的鎖資訊,導致有可能出現兩個客戶端同時持有同一把鎖。
    舉例:
    a. client A 在master拿到鎖
    b. master節點把A建立的鎖資訊同步到slave之前宕機了
    c. slave晉升為master節點
    d. client B 在新master拿到與A相同的鎖(此時A以為自己仍持有鎖)

…TODO

Redisson使用DEMO程式碼片段:

使用Redisson加鎖 釋放鎖業務程式碼
使用Redisson加鎖 釋放鎖業務程式碼lock例項化RedissonClient