Java实现Redis分布锁
1、背景:
在多線程環境下,通常會使用鎖來保證有且只有一個線程來操作共享資源。比如:
object obj = new object();lock (obj)?
{?
//操作共享資源?
}
利用操作系統提供的鎖機制,可以確保多線程或多進程下的并發唯一操作。但如果在多機環境下就不能滿足了,當A,B兩臺機器同時操作C機器的共享資源時,就需要第三方的鎖機制來保證在分布式環境下的資源協調,也稱分布式鎖。
在分布式環境下(多節點主機)加鎖處理場景,如:秒殺、全局遞增ID等等,需要對資源(變量)同步互斥。大部分的解決方案是基于DB實現的,Redis為單進程單線程模式,采用隊列模式將并發訪問變成串行訪問,且多客戶端對Redis的連接并不存在競爭關系。由于Redis是單線程模型,命令操作原子性,所以利用這個特性可以很容易的實現分布式鎖。
2、Redis有三個最基本屬性來保證分布式鎖的有效實現:
安全性: 互斥,在任何時候,只有一個客戶端能持有鎖。
活躍性A:沒有死鎖,即使客戶端在持有鎖的時候崩潰,最后也會有其他客戶端能獲得鎖,超時機制。
活躍性B:故障容忍,只有大多數Redis節點時存活的,客戶端仍可以獲得鎖和釋放鎖。
使用Redis實現分布式鎖,有兩個重要函數需要介紹
1)SETNX命令(SET if Not eXists)
語法:
SETNX key value
功能:
當且僅當 key 不存在,將 key 的值設為 value ,并返回1;若給定的 key 已經存在,則 SETNX 不做任何動作,并返回0。
2)GETSET命令
語法:
GETSET key value
功能:
將給定 key 的值設為 value ,并返回 key 的舊值 (old value),當 key 存在但不是字符串類型時,返回一個錯誤,當key不存在時,返回nil。
3、代碼:
package ct.tool;import redis.clients.jedis.Jedis;public class RedisDisLock {private static final long expired = 1000;//1秒超時//上鎖public static boolean acquireLock(Jedis jedis,String lock) {// 1. 通過SETNX試圖獲取一個lockboolean success = false;long value = System.currentTimeMillis() + expired + 1; long acquired = jedis.setnx(lock, String.valueOf(value));jedis.expire(lock, 1);//設置1秒超時//SETNX成功,則成功獲取一個鎖if (acquired == 1) success = true;//SETNX失敗,說明鎖被其他客戶端保持,檢查其是否已經超時/*else {long oldValue = Long.valueOf(jedis.get(lock)); if (oldValue < System.currentTimeMillis()) {//超時//獲取上一個鎖到期時間,并設置現在的鎖到期時間,//只有一個線程才能獲取上一個線上的設置時間,因為jedis.getSet是同步的String getValue = jedis.getSet(lock, String.valueOf(value));if (getValue !=null) {if (Long.valueOf(getValue) == oldValue) success = true; else success = false;// 已被其他進程捷足先登了} }else //未超時,則直接返回失敗success = false;} */return success; }//釋放鎖public static void releaseLock(Jedis jedis,String lock) { //long current = System.currentTimeMillis(); // 避免刪除非自己獲取得到的鎖//if (current < Long.valueOf(jedis.get(lock)))jedis.del(lock); }}代碼應用中,要共享的代碼段前加: //枷鎖boolean lockFlag=true;while(lockFlag){//循環等待拿鎖if (RedisDisLock.acquireLock(jd,"o2o")) lockFlag=false;}
業務處理后,釋放: RedisDisLock.releaseLock(jd, "o2o");
總結
以上是生活随笔為你收集整理的Java实现Redis分布锁的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java定时多线程任务实现(TimerT
- 下一篇: centos下排查vsftpd出现put