淺析Redis實現lock互斥訪問資源

來源:互聯網
上載者:User

淺析Redis實現lock互斥訪問資源

Redis是當前很流行的一種開源索引值資料庫。目前睿思的後台架構在資料庫層採用了Redis和MySQL組合的形式,其中Redis主要用來儲存狀態資訊(比如當前種子的peer)和讀寫頻繁的資料。Redis完全運行在記憶體之上,無lock設計,速度非常快!通過實測,在睿思伺服器上讀寫速度達到3萬次/s。

在高並發的應用中,很多時候我們需要對某些資源進行競爭訪問,比如在很多人下載一個熱門資源,就可能存在很多請求去修改某個資源的peer資訊(就是儲存了當前保種人的ip地址和連接埠號碼),需要保證某個請求修改peer資訊的時候,不允許其他請求修改,否則就會出現資料覆蓋的問題。但是Redis沒有提供對資料的加鎖,所以需要我們通過Redis提供的命令自己實現:

思路一:通過get 和set 命令實現

這種方式很容易想到,就是當每次請求到來時通過get判斷這個鎖是否存在,如果不存在則set建立。這種方法有一個弊端,由於get和set是兩次Redis請求,二者之間有延時,在高並發的環境下,有可能在get檢測到鎖不存之後在set之前已經被其他線程set,這時當前線程再set,這樣鎖就失效了。所以這種方法只能應對並發量不是很高的情況。

思路二:通過setnx 和 expire命令實現

在訪問需要互斥訪問的資源時,通過setnx命令去設定一個lock 鍵,setnx的作用是判斷鎖是否存在,如果不存在則建立,返回成功,如果存在則返回失敗,伺服器返回給用戶端,指示用戶端稍後重試。expire命令用於給該鎖設定一個到期時間,用於防止線程crash,導致鎖一直有效,從而導致死結。例如:設定鎖的有效期間為100秒,那麼即使線程奔潰,在100秒後鎖會自動失效。

setnx lock "lock"

如果成功則設定到期時間

expire lock 100

訪問互斥資源結束後,刪除鎖

del lock

思路三:通過watch和Redis的事務命令實現

這種方式的效果和思路二類似。在請求到時先watch改資源鎖,然後再通過在事務執行 建立鎖的過程,鎖的索引值能唯一標識改請求(比如用時間+使用者標識)。如果當前還有其他線程請求該資源,當判斷該鎖存在時則返回錯誤重試(例如睿思BT tracker返回“伺服器過載,自動重試的”的提示就屬於此類情況)。如果有多個請求同時判斷改鎖不存在而建立鎖,這樣也會由於watch了這個鎖,導致之前watch的線程執行事務失敗,返回用戶端自動重試。這樣達最終達到了鎖的目的。

Ubuntu 14.04下Redis安裝及簡單測試

Redis叢集明細文檔

Ubuntu 12.10下安裝Redis(圖文詳解)+ Jedis串連Redis

Redis系列-安裝部署維護篇

CentOS 6.3安裝Redis

Redis安裝部署學習筆記

Redis設定檔redis.conf 詳解

Redis 的詳細介紹:請點這裡
Redis 的:請點這裡

本文永久更新連結地址:

相關文章

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.