原理:使用setnx,設定成功返回1,失敗返回0,由於redis也是單執行緒的,所以一次只能有乙個執行緒獲取成功。
程式異常情況:設定超時時間,避免程式掛掉鎖無法釋放。
執行超時情況:為避免**執行時間超過key設定的超時時間,從而釋放了其他程序的鎖問題。需要儲存當前執行緒的value。在釋放之前先檢查key設定的value是否跟當前相等,類似cas的思想,比較再刪除。
資源釋放:如果查詢key的value與當前設定的value相等,再進行刪除。這兩步不是原子操作的,也會有問題。比如兩個操作之前有網路延遲。 可以使用lua指令碼來釋放鎖。
分布式鎖**如下:
public class redisdsclock
}//用完之後,必須釋資源,否則會導致無連線池可用。
throw new timeoutexception("獲取鎖超時");
}private string getlockkey(string key)
/*** 執行結束的指令碼
*/private static string lua = " if redis.call(\"get\",keys[1])== ar**[1] " +
"then return redis.call(\"del\",ar**[1]) " +
"else return 0 " +
"end";
/*** 使用lua指令碼 查詢和刪除的原子操作
** @param key
* @param value
* @return
*/public long releaselockbylua(jedis jedis, string key, string value)
system.out.println(thread.currentthread().getname() + " release lock");
key = getlockkey(key);
long res = (long) jedis.eval(lua, arrays.aslist(key), arrays.aslist(value));
system.out.println(thread.currentthread().getname() + " release lock success");
jedis.close();
return res;
}}
測試**
public class redislockdemo
public static void main(string args) throws interruptedexception, timeoutexception, brokenbarrierexception catch (timeoutexception e) catch (exception e) finally catch (exception e)
if (jedis != null)
countdownlatch.countdown();}}
});}
//等待所有執行緒執行完畢
countdownlatch.await();
system.out.println("remain goods" + goodsnum);
pool.shutdown();
}}
單機Redis實現分布式鎖
最近有個專案用到了鎖,直接想到了redis,在網上檢視了一下案列,總感覺不是特別符合需求,索性自己寫了乙個。不多說,直接上 class redis lock 單機redis 分布式鎖 class redis lock 單台redis設定鎖 param string key param int exp...
redis 單機鎖 和 分布式鎖
偷自 require vendor autoload.php client new predis client scheme tcp host 127.0.0.1 port 6379,class redislock desc 獲取鎖鍵名 public function getlockcachekey...
Redis實現分布式鎖(單機版)
一 前言 在我們日常工作中,除了spring和mybatis外,用到最多無外乎分布式快取框架 redis。但是很多任務作很多年的朋友對redis還處於乙個最基礎的使用和認識。所以我就像把自己對分布式快取的一些理解和應用整理乙個系列,希望可以幫助到大家加深對redis的理解。本系列的文章思路先從red...