Memcached 和 Redis 分布式鎖方案

來源:互聯網
上載者:User

標籤:style   blog   http   color   io   os   ar   使用   strong   

分布式緩衝,能解決單台伺服器記憶體不能無限擴張的瓶頸。在分布式緩衝的應用中,會遇到多個用戶端同時爭用的問題。這個時候,需要用到分布式鎖,得到鎖的用戶端才有操作許可權。

Memcached 和 Redis 是常用的分布式緩衝構建方案,下面列舉下基於Memcached 和 Redis 分布式鎖的實現方法。

Memcached 分布式鎖

Memcached 可以使用 add 命令,該命令只有KEY不存在時,才進行添加,或者不會處理。Memcached 所有命令都是原子性的,並發下add 同一個KEY ,只會一個會成功。

利用這個原理,可以先定義一個 鎖 LockKEY ,add 成功的認為是得到鎖。並且設定[到期逾時] 時間,保證宕機後,也不會死結

在具體操作完後,判斷是否此次操作已逾時。如果逾時則不刪除鎖,如果不逾時則刪除鎖。

虛擬碼:

 1          if (mc.Add("LockKey", "Value", expiredtime)) 2             { 3                 //得到鎖 4                 try 5                 { 6                     //do business  function 7  8                     //檢查逾時 9                     if (!CheckedTimeOut())10                     {11                         mc.Delete("LockKey");12                     }13                 }14                 catch (Exception e)15                 {16                     mc.Delete("LockKey");17                 }18                19             }

 

Redis 分布式鎖

Redis  沒有add 命令,但有SETNX(SET if Not eXists)若給定的 key 已經存在,則 SETNX不做任何動作。設定成功,返回 1 。設定失敗,返回 0 。

SETNX 命令不能設定到期時間,需要再使用 EXPIRE 命令設定到期時間。

虛擬碼:

            int lockResult = rd.SETNX("LockKey", "Value");            if (lockResult == 1)            {                //[1]得到鎖                //[2]設定逾時到期時間                rd.EXPIRE("LockKey", expiredtime);                try                {                    //do business  function                    //檢查逾時                    if (!CheckedTimeOut())                    {                        rd.DEL("LockKey");                    }                }                catch (Exception e)                {                    rd.DEL("LockKey");                }            }

   這種做法,有一個很大的潛在風險。[1]得到鎖後,再執行[2] 設定到期時間。如果在這期間出現宕機,則會導致沒有設定到期時間。按Redis 的預設緩衝到期策略,這個鎖將不會釋放,產生死結。

所以不推薦用這種做法,應該用其它方式來實現鎖的逾時到期策略:

     1:SETNX  value 值=目前時間+到期逾時時間,返回1 則獲得鎖,返回0則沒有獲得鎖。轉2。

     2:GET 擷取 value 的值 。判斷鎖是否到期逾時。如果逾時,轉3。

     3:GETSET(將給定 key 的值設為 value ,並返回 key 的舊值),GETSET  value 值=目前時間+到期逾時時間, 判斷得到的value 如果仍然是逾時的,那就說明得到鎖,否則沒有得到鎖。

從2並發進到3 的操作,會多次改寫逾時時間,但這個不會有什麼影響。

虛擬碼:

 

            string expiredtime = DateTime.Now.AddMinutes(LockTimeoutMinutes).ToString();            int lockResult = rd.SETNX("LockKey", expiredtime);            bool getLock = false;            if (lockResult == 1)            {                //得到鎖                getLock = true;            }            else            {                string curExpiredtime = rd.GET("LockKey");                //檢查鎖逾時                if (CheckedLockTimeOut(expiredtime))                {                    expiredtime = DateTime.Now.AddMinutes(LockTimeoutMinutes).ToString();                    string newExpiredTime = GETSET(expiredtime);                    if (CheckedLockTimeOut(newExpiredTime))                    {                        //得到鎖                        getLock = true;                    }                }            }            if (getLock)            {                try                {                    //do business  function                    //檢查逾時                    if (!CheckedTimeOut())                    {                        rd.DEL("LockKey");                    }                }                catch (Exception e)                {                    rd.DEL("LockKey");                }            }

個人覺得這種做法,還是不完美。 

ZooKeeper的分布式鎖,下篇再學習探討。

 

參考:

鄭昀, 電商課題V:分布式鎖jeffkit, 用Redis實現分布式鎖 

Memcached 和 Redis 分布式鎖方案

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.