天天看點

Redis鎖的簡單應用

本文版權歸部落格園和作者本人吳雙共同所有 。轉載爬蟲請注明位址,部落格園蝸牛 http://www.cnblogs.com/tdws/p/5712835.html

蝸牛Redis系列文章目錄http://www.cnblogs.com/tdws/tag/NoSql/

Redis Cluster http://www.cnblogs.com/tdws/p/7710545.html

其實說多線程修改資料也不合适,畢竟redis服務端是單線程的,所有指令串行執行,隻是在用戶端并發發送指令的時候,導緻串行的指令一些排列問題和網絡時間差等造成資料不一緻。本文雖然是數字的加減,但是為了說明鎖的情況,故意不是用原子指令incr。也并非分布式鎖的正确實作,沒有考慮一些重入性等,稍後會整理一篇分布式鎖的實踐。

Redis分布式鎖 http://www.cnblogs.com/tdws/p/5808528.html

ZK+curator 分布式鎖 http://www.cnblogs.com/tdws/p/5874686.html

先配上一個簡易的RedisHelper,一個set值,一個get值,一個設定并發鎖,以便在我後面的操作中,你能清楚我究竟做了什麼。

 下面看一下并發代碼,我隻new了兩個Thread。兩個線程同時想通路同一個key,分别通路五萬次,在并發條件下,我們很難保證資料的準确性,請比較輸出結果。

Redis鎖的簡單應用

是的,和我們單線程,跑兩個50000,會輸出100000。現在是兩個并發線程同時跑在由于并發造成的資料結果往往不是我們想要的。那麼如何解決這個問題呢,Redis已經為我們準備好了!

你可以看到我RedisHelper中有個方法是 public IDisposable Acquire(string key)。  也可以看到他傳回的是IDisposable,證明我們需要手動釋放資源。方法内部的 AcquireLock正是關鍵之處,它像redis中索取一把鎖頭,被鎖住的資源,隻能被單個線程通路,不會被兩個線程同時get或者set,這兩個線程一定是交替着進行的,當然這裡的交替并不是指你一次我一次,也可能是你多次,我一次,下面看代碼。

 可以看到我使用了using,調用我的Acquire方法擷取鎖。

Redis鎖的簡單應用

輸出結果最後是100000,正是我們要的正确結果。前面的8W+是因為兩個線程之一先執行結束了。

還有,在正式使用的過程中,建議給我們的鎖,使用後删除掉,并加上一個過期時間,使用expire。

以免程式執行期間意外退出,導緻鎖一直存在,今後可能無法更新或者擷取此被鎖住的資料。

你也可以嘗試一下不設定expire,在程式剛開始執行時,關閉console,重新運作程式,并且在redis-cli的操作控制台,get你鎖住的值,将會永遠擷取不到。

所有連接配接此redis執行個體的機器,同一時刻,隻能有一個擷取指定name的鎖.

下面是StackExchange.Redis的寫法

Redis鎖的簡單應用
Redis鎖的簡單應用