Redis 分佈式鎖,C#經過Redis實現分佈式鎖(轉)

分佈式鎖通常有三種實現方式:

  1. 數據庫樂觀鎖;數據庫

  2. 基於Redis的分佈式鎖;less

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

可靠性

  首先,爲了確保分佈式鎖可用,咱們至少要確保鎖的實現同時知足如下四個條件:ui

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

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

  具備容錯性。只要大部分的Redis節點正常運行,客戶端就能夠加鎖和解鎖。博客

  解鈴還須繫鈴人。加鎖和解鎖必須是同一個客戶端,客戶端本身不能把別人加的鎖給解了。string

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

/// <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);
}

調用實現class

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

相關文章
相關標籤/搜索