分散式鎖定其實可以理解為:控制分散式系統有序的去對共享資源進行操作,透過互斥來保持一致性。
舉個不太恰當的例子:假設共享的資源就是一個房子,裡面有各種書,分散式系統就是要進屋看書的人,分散式鎖就是保證這個房子只有一個門並且一次只有一個人可以進,而且門只有一把鑰匙。 (建議學習:Redis影片教學)
#使用redis實作分散式鎖定
編號# -lock-time 實作加鎖
使用redis指令EVAL 實作解鎖
#加鎖:
Jedis jedis = new Jedis("127.0.0.1", 6379); private static final String SUCCESS = "OK"; /** * 加锁操作 * @param key 锁标识 * @param value 客户端标识 * @param timeOut 过期时间 */ public Boolean lock(String key,String value,Long timeOut){ String var1 = jedis.set(key,value,"NX","EX",timeOut); if(LOCK_SUCCESS.equals(var1)){ return true; } return false; }
解讀:
加上鎖定操作:jedis.set(key,value,"NX","EX",timeOut)【保證加鎖的原子操作】 key就是redis的key值作為鎖的標識,value在這裡作為客戶端的標識,只有key-value都比配才有刪除鎖的權利【保證安全性】透過timeOut設定過期時間保證不會出現死鎖【避免死鎖】NX,EX什麼意思?
NX:只有這個key不存才的時候才會進行操作,if not exists;EX:設定key的過期時間為秒,具體時間由第5個參數決定解鎖
Jedis jedis = new Jedis("127.0.0.1", 6379); private static final Long UNLOCK_SUCCESS = 1L; /** * 解锁操作 * @param key 锁标识 * @param value 客户端标识 * @return */ public static Boolean unLock(String key,String value){ String luaScript = "if redis.call(\"get\",KEYS[1]) == ARGV[1] then return redis.call(\"del\",KEYS[1]) else return 0 end"; Object var2 = jedis.eval(luaScript,Collections.singletonList(key), Collections.singletonList(value)); if (UNLOCK_SUCCESS == var2) { return true; } return false; }
解讀:
luaScript 這個字串是個lua腳本,代表的意思是如果根據key拿到的value跟傳入的value相同就執行del,否則就回傳0【保證安全性】jedis.eval(String,list,list);這個指令就是去執行lua腳本,KEYS的集合就是第二個參數,ARGV的集合就是第三參數【保證解鎖的原子操作】上述就實現了怎麼使用redis去正確的實現分散式鎖,但是有個小缺陷就是鎖過期時間要設定為多少合適,這個其實還是需要去依照業務場景來考慮的。 更多Redis相關技術文章,請造訪Redis入門教學欄位學習!
以上是如何使用redis來實現分散式鎖的詳細內容。更多資訊請關注PHP中文網其他相關文章!