假設商品有500件庫存,進行**預購,每有一位客戶預購,商品預購數numvalue加1。
省略資料庫的操作,用redis儲存預購數
假設有多人同時預購該商品,這必然涉及到多人同時去更新redis的情況,這時候資料可能會出現不一致,當然如果在伺服器端加鎖可以保證資料的一致性,但是這種情況只能保證單價伺服器併發操作時redis的商品預購數資料更新正常。假設在分布式系統中,伺服器有a,b,c三颱,三颱伺服器同時去redis去獲取numvalue值,然後三颱伺服器同時加1,再更新到redis中,正常numvalue的值應該是加3,而實際上可能只加了1,所以這時候就該考慮是否在併發匯集點(redis)中使用分布式鎖了。
鎖是為了在多人同時運算元據時,為了讓資料不失真,操作上有序進行而存在的。基本上鎖要滿足下面的條件:
互斥性,同一時間,只能有乙個人有鎖
不死鎖,如果獲得鎖的那個人出現了阻塞,無法手動解鎖,鎖也可以自動解鎖
誰加的鎖只能讓那個人解鎖,其他人無法加鎖(獲得鎖的人無法解鎖時自動解鎖)
拿現實舉例子:把我們的要做的邏輯放到乙個房間中,只有在房間中才能完成我們的邏輯,而進房間需要乙個鑰匙,誰都可以拿鑰匙進房間,進房間會關門並帶上鑰匙,其他人都無法進入。這樣就能保證每次只有乙個人可以去做我們的業務邏輯。當邏輯完成後那個人開門再把鑰匙拿出來,一切就回到一開始的狀態,下乙個人要再做同樣邏輯時就重複上述步驟。(阻塞的時候就相當於這個人一直呆在房間裡不出來,這個時候就需要手動解鎖,房間可以自動開啟,鑰匙也可以再拿出來)
有時候鎖不一定是真正意義上的鎖,也可以是概念上的鎖,只要滿足鎖的要求即可。redis就可以用set 命令來實現鎖的功能:
reids set命令:set key value nx ex timeout ; nx 和 ex可以網上了解引數的意義,我就不解釋了。主要是timeout 這個引數,是這個鍵值對在redis的中儲存有效時間
如果我們timeout 設值 3秒,執行下面語句,然後3秒內再執行一次,第二次跑set命令就不會返回ok,只有在3秒後再執行才會返回ok,這個3秒後自動刪除鍵值對就相當於自動解鎖,而當乙個鍵值對賦值後,3秒內就不能用其他人在用相同語句賦值,這個就滿足了鎖的互質性(value不一定要用固定的666,一般都用uuid中獲取唯一的id來做請求標識)
用lua指令碼去寫手動解鎖邏輯,就滿足了鎖的誰加的鎖誰解鎖的要求
以上,redis的分布式鎖設計思路基本完成
初始化引數:
private string lock_key = "my_lock"; // 鎖的key 值
private long timeout = 3;// 鎖的有效時間
private long trytime = 40000;// 使用者最長的等待時間
private long waittime = 1000;// 使用者自旋等待時間
jedispool jedispool = new jedispool("127.0.0.1" , 6379);
public redislockutil()
public jedis getjedis()
上鎖方法:
/**
* 加鎖
* * @param id
* @return
*/public boolean lock(string id) catch (exception e)
if ("ok".equals(lock)) else
// 沒獲取到鑰匙
long l = system.currenttimemillis() - start;
if (l >= trytime)
// 等待100毫秒,再自旋再次去搶鑰匙
try catch (interruptedexception e)
}} finally
}
解鎖方法:
/**
* 解鎖
總的還是實現了redis的分布式鎖,但是問題也很明顯,控制台列印了很多行,而且「鑰匙已被拿走」 這句話列印了400+次,同乙個使用者競爭鎖失敗的次數很高,還是待優化的,根據實際情況去修改,當然本人電腦也有點渣,沒辦法提現redis的特性,動態的調整初始化引數的值,可以檢視到不同的結果,有時候等待時間太短,也可能會有使用者等待超時放棄競爭鎖的情況,總之就是路漫漫,根據實際情況,酌情使用
redis分布式鎖
redis分布式鎖 直接上 我寫了四個redis分布式鎖的方法,大家可以提個意見 第一種方法 redis分布式鎖 param timeout public void lock long timeout thread.sleep 100 catch exception e override publi...
Redis分布式鎖
分布式鎖一般有三種實現方式 1.資料庫樂觀鎖 2.基於redis的分布式鎖 3.基於zookeeper的分布式鎖.首先,為了確保分布式鎖可用,我們至少要確保鎖的實現同時滿足以下四個條件 互斥性。在任意時刻,只有乙個客戶端能持有鎖。不會發生死鎖。即使有乙個客戶端在持有鎖的期間崩潰而沒有主動解鎖,也能保...
redis分布式鎖
使用redis的setnx命令實現分布式鎖 redis為單程序單執行緒模式,採用佇列模式將併發訪問變成序列訪問,且多個客戶端對redis的連線並不存在競爭關係。redis的setnx命令可以方便的實現分布式鎖。setnx key value 將key的值設為value,當且僅當key不存在。如給定的...