Redis 分布式鎖,C#通過Redis實現分布式鎖(轉)


分布式鎖一般有三種實現方式:

  1. 數據庫樂觀鎖;

  2. 基於Redis的分布式鎖;

  3. 基於ZooKeeper的分布式鎖。本篇博客將介紹第二種方式,基於Redis實現分布式鎖。雖然網上已經有各種介紹Redis分布式鎖實現的博客,然而他們的實現卻有着各種各樣的問題,為了避免誤人子弟,本篇博客將詳細介紹如何正確地實現Redis分布式鎖。

可靠性

  首先,為了確保分布式鎖可用,我們至少要確保鎖的實現同時滿足以下四個條件:

  互斥性。在任意時刻,只有一個客戶端能持有鎖。

  不會發生死鎖。即使有一個客戶端在持有鎖的期間崩潰而沒有主動解鎖,也能保證后續其他客戶端能加鎖。

  具有容錯性。只要大部分的Redis節點正常運行,客戶端就可以加鎖和解鎖。

  解鈴還須系鈴人。加鎖和解鎖必須是同一個客戶端,客戶端自己不能把別人加的鎖給解了。

使用StackExchange.Redis 實現起來簡單得很

/// <summary>
/// 加鎖,如果鎖定成功,就去執行方法
/// </summary>
public static bool LockTake(string key, string data, int seconds, int db = 0)
{
    // key:用key來當鎖,因為key是唯一的。
    // value:很多童鞋可能不明白,有key作為鎖不就夠了嗎,為什么還要用到value?原因就是我們在上面講到可靠性時,
    // 分布式鎖要滿足第四個條件解鈴還須系鈴人,通過給value賦值為Guid.NewGuid().ToString(),我們就知道這把鎖是哪個請求加的了,在解鎖的時候就可以有依據。
    return GetDatabase(db).LockTake(key, data, (DateTime.Now.AddSeconds(seconds) - DateTime.Now));
}
 
/// <summary>
/// 解鎖
/// </summary>
public static bool LockRelease(string key, string data, int db = 0)
{
    return GetDatabase(db).LockRelease(key, data);
}

調用實現

string guid = Guid.NewGuid().ToString();
if (RedisHelper.LockTake(wechatOpenId, guid, 90, 15))
{
    try
    {
        // 執行方法
    }
    catch (Exception e)
    {
        // 異常
    }
    finally
    {
        RedisHelper.LockRelease(wechatOpenId, guid, 15);
    }
}
else {
    // 已鎖,無法執行
    return null;
}

Ruthless https://notes.clump.cc/technology/3348


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM