亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 數據庫 > Redis > 正文

Redis分布式鎖的實現方式(redis面試題)

2020-10-28 21:28:30
字體:
來源:轉載
供稿:網友

什么是分布式鎖?

要介紹分布式鎖,首先要提到與分布式鎖相對應的是線程鎖、進程鎖。

線程鎖:主要用來給方法、代碼塊加鎖。當某個方法或代碼使用鎖,在同一時刻僅有一個線程執行該方法或該代碼段。線程鎖只在同一JVM中有效果,因為線程鎖的實現在根本上是依靠線程之間共享內存實現的,比如synchronized是共享對象頭,顯示鎖Lock是共享某個變量(state)。

進程鎖:為了控制同一操作系統中多個進程訪問某個共享資源,因為進程具有獨立性,各個進程無法訪問其他進程的資源,因此無法通過synchronized等線程鎖實現進程鎖。

分布式鎖:當多個進程不在同一個系統中,用分布式鎖控制多個進程對資源的訪問。

前言

現在的業務場景越來越復雜,使用的架構也就越來越復雜,分布式、高并發已經是業務要求的常態。像騰訊系的不少服務,還有CDN優化、異地多備份等處理。

說到分布式,就必然涉及到分布式鎖的概念,如何保證不同機器不同線程的分布式鎖同步呢?

實現要點

  1. 互斥性,同一時刻,智能有一個客戶端持有鎖。
  2. 防止死鎖發生,如果持有鎖的客戶端崩潰沒有主動釋放鎖,也要保證鎖可以正常釋放及其他客戶端可以正常加鎖。
  3. 加鎖和釋放鎖必須是同一個客戶端。
  4. 容錯性,只有redis還有節點存活,就可以進行正常的加鎖解鎖操作。

正確的redis分布式鎖實現

錯誤加鎖方式

錯誤方式一

保證互斥和防止死鎖,首先想到的使用redis的setnx命令保證互斥,為了防止死鎖,鎖需要設置一個超時時間。

 public static void wrongLock(Jedis jedis, String key, String uniqueId, int expireTime) {  Long result = jedis.setnx(key, uniqueId);  if (1 == result) {   //如果該redis實例崩潰,那就無法設置過期時間了   jedis.expire(key, expireTime);  } }

在多線程并發環境下,任何非原子性的操作,都可能導致問題。這段代碼中,如果設置過期時間時,redis實例崩潰,就無法設置過期時間。如果客戶端沒有正確的釋放鎖,那么該鎖(永遠不會過期),就永遠不會被釋放。

錯誤方式二

比較容易想到的就是設置值和超時時間為原子原子操作就可以解決問題。那使用setnx命令,將value設置為過期時間不就ok了嗎?

public static boolean wrongLock(Jedis jedis, String key, int expireTime) {  long expireTs = System.currentTimeMillis() + expireTime;  // 鎖不存在,當前線程加鎖成果  if (jedis.setnx(key, String.valueOf(expireTs)) == 1) {   return true;  }  String value = jedis.get(key);  //如果當前鎖存在,且鎖已過期  if (value != null && NumberUtils.toLong(value) < System.currentTimeMillis()) {   //鎖過期,設置新的過期時間   String oldValue = jedis.getSet(key, String.valueOf(expireTs));   if (oldValue != null && oldValue.equals(value)) {    // 多線程并發下,只有一個線程會設置成功    // 設置成功的這個線程,key的舊值一定和設置之前的key的值一致    return true;   }  }  // 其他情況,加鎖失敗  return true; }

乍看之下,沒有什么問題。但仔細分析,有如下問題:

value設置為過期時間,就要求各個客戶端嚴格的時鐘同步,這就需要使用到同步時鐘。即使有同步時鐘,分布式的服務器一般來說時間肯定是存在少許誤差的。

鎖過期時,使用 jedis.getSet雖然可以保證只有一個線程設置成功,但是不能保證加鎖和解鎖為同一個客戶端,因為沒有標志鎖是哪個客戶端設置的嘛。

錯誤解鎖方式

解鎖錯誤方式一

直接刪除key

public static void wrongReleaseLock(Jedis jedis, String key) {  //不是自己加鎖的key,也會被釋放  jedis.del(key); }

簡單粗暴,直接解鎖,但是不是自己加鎖的,也會被刪除,這好像有點太隨意了吧!

解鎖錯誤方式二

判斷自己是不是鎖的持有者,如果是,則只有持有者才可以釋放鎖。

 public static void wrongReleaseLock(Jedis jedis, String key, String uniqueId) {  if (uniqueId.equals(jedis.get(key))) {   // 如果這時鎖過期自動釋放,又被其他線程加鎖,該線程就會釋放不屬于自己的鎖   jedis.del(key);  } }

看起來很完美啊,但是如果你判斷的時候鎖是自己持有的,這時鎖超時自動釋放了。然后又被其他客戶端重新上鎖,然后當前線程執行到jedis.del(key),這樣這個線程不就刪除了其他線程上的鎖嘛,好像有點亂套了哦!

正確加鎖釋放鎖方式

基本上避免了以上幾種錯誤方式之外,就是正確的方式了。要滿足以下幾個條件:

命令必須保證互斥

設置的key必須要有過期時間,防止崩潰時鎖無法釋放

value使用唯一id標志每個客戶端,保證只有鎖的持有者才可以釋放鎖

加鎖直接使用set命令同時設置唯一id和過期時間;其中解鎖稍微復雜些,加鎖之后可以返回唯一id,標志此鎖是該客戶端鎖擁有;釋放鎖時要先判斷擁有者是否是自己,然后刪除,這個需要redis的lua腳本保證兩個命令的原子性執行。

下面是具體的加鎖和釋放鎖的代碼:

@Slf4jpublic class RedisDistributedLock { private static final String LOCK_SUCCESS = "OK"; private static final Long RELEASE_SUCCESS = 1L; private static final String SET_IF_NOT_EXIST = "NX"; private static final String SET_WITH_EXPIRE_TIME = "PX"; // 鎖的超時時間 private static int EXPIRE_TIME = 5 * 1000; // 鎖等待時間 private static int WAIT_TIME = 1 * 1000; private Jedis jedis; private String key; public RedisDistributedLock(Jedis jedis, String key) {  this.jedis = jedis;  this.key = key; } // 不斷嘗試加鎖 public String lock() {  try {   // 超過等待時間,加鎖失敗   long waitEnd = System.currentTimeMillis() + WAIT_TIME;   String value = UUID.randomUUID().toString();   while (System.currentTimeMillis() < waitEnd) {    String result = jedis.set(key, value, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, EXPIRE_TIME);    if (LOCK_SUCCESS.equals(result)) {     return value;    }    try {     Thread.sleep(10);    } catch (InterruptedException e) {     Thread.currentThread().interrupt();    }   }  } catch (Exception ex) {   log.error("lock error", ex);  }  return null; } public boolean release(String value) {  if (value == null) {   return false;  }  // 判斷key存在并且刪除key必須是一個原子操作  // 且誰擁有鎖,誰釋放  String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";  Object result = new Object();  try {   result = jedis.eval(script, Collections.singletonList(key),     Collections.singletonList(value));   if (RELEASE_SUCCESS.equals(result)) {    log.info("release lock success, value:{}", value);    return true;   }  } catch (Exception e) {   log.error("release lock error", e);  } finally {   if (jedis != null) {    jedis.close();   }  }  log.info("release lock failed, value:{}, result:{}", value, result);  return false; }}

單是一個redis的分布式鎖就有這么多道道,不知道你是否看明白了?留言討論下吧!

總結

以上所述是小編給大家介紹的Redis分布式鎖的實現方式(redis面試題),希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對武林網網站的支持!如果你覺得本文對你有幫助,歡迎轉載,煩請注明出處,謝謝!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩av三级在线观看| 亚洲理论在线a中文字幕| 91精品视频一区| 亚洲精品欧美一区二区三区| 欧美性高潮在线| 国产成人激情视频| 日韩精品高清在线| 欧美肥老太性生活视频| 国内精品美女av在线播放| 亚洲片在线资源| 国产精品白嫩美女在线观看| 成人免费淫片aa视频免费| 亚洲一区二区免费| 91久久久精品| 国产亚洲一区精品| 欧美大片欧美激情性色a∨久久| 欧美麻豆久久久久久中文| 大胆人体色综合| 国产精品欧美一区二区三区奶水| 欧美重口另类videos人妖| 久久五月天色综合| 国产视频精品一区二区三区| 亚洲精品第一国产综合精品| 精品国偷自产在线| 国产精品久久久久久久久久尿| 日韩hd视频在线观看| 日韩在线欧美在线国产在线| 成人中文字幕+乱码+中文字幕| 亚洲在线免费看| 性欧美激情精品| 精品美女久久久久久免费| 一本大道久久加勒比香蕉| 欧美日韩一区二区三区在线免费观看| 久久久久久久国产精品| 久久精品国产欧美亚洲人人爽| 亚洲综合色av| 中文字幕日韩高清| 欧美电影免费观看电视剧大全| 日韩美女视频在线观看| 国产精品丝袜久久久久久高清| 久久久久久久久国产精品| 欧美黄色小视频| 91色在线视频| 欧美裸体男粗大视频在线观看| 欧美中文字幕第一页| 日韩欧美精品网址| 日韩中文字幕网址| 亚洲国产成人久久| 国产精品一区二区三区久久久| 精品国产乱码久久久久久天美| 国产精品视频网站| 国产成人综合av| 日本视频久久久| 美女扒开尿口让男人操亚洲视频网站| 超碰91人人草人人干| 亚洲激情第一页| 欧美日韩在线视频一区| 亚洲精品资源在线| 日韩动漫免费观看电视剧高清| 欧美激情久久久久久| 亚洲大胆人体av| 日韩精品在线免费观看| 亚洲视频999| 91国自产精品中文字幕亚洲| 91久久综合亚洲鲁鲁五月天| 国产亚洲精品久久久久久牛牛| 欧美一级视频一区二区| 91精品国产色综合久久不卡98| 亚洲在线观看视频网站| 九九热精品视频国产| 国产精品久久久久久久午夜| 欧美激情第一页xxx| 欧美性猛交丰臀xxxxx网站| 国外成人免费在线播放| 欧美日本精品在线| 亚洲va欧美va国产综合久久| 在线观看中文字幕亚洲| 性亚洲最疯狂xxxx高清| 国产欧美一区二区三区在线看| 91九色国产视频| 97视频在线观看亚洲| 久久伊人精品视频| 亚洲精品av在线播放| 欧美不卡视频一区发布| 久久色免费在线视频| 日韩精品在线免费观看| 超碰日本道色综合久久综合| 亚洲成av人片在线观看香蕉| 亚洲大胆人体视频| 国产色婷婷国产综合在线理论片a| 大胆人体色综合| 亚洲在线观看视频| 国产精品视频地址| 日韩日本欧美亚洲| 不卡伊人av在线播放| 欧美精品免费看| 国产精品一二三在线| 在线观看欧美日韩国产| 97色伦亚洲国产| zzjj国产精品一区二区| 97精品在线观看| 久久99国产精品自在自在app| 国产日韩在线播放| 欧美另类极品videosbest最新版本| 91久久久久久| 国产欧美精品日韩| 欧美日韩成人在线视频| 色噜噜久久综合伊人一本| 北条麻妃一区二区在线观看| 一区二区福利视频| 日韩视频免费中文字幕| 亚洲精品日韩av| 九九热最新视频//这里只有精品| 91免费精品国偷自产在线| 国产在线精品播放| 国产欧美一区二区白浆黑人| 国产一区二区三区久久精品| 欧美高清在线视频观看不卡| 欧美丝袜一区二区三区| 欧美专区在线视频| 欧美人在线视频| 粉嫩老牛aⅴ一区二区三区| 久久影院在线观看| 精品久久中文字幕久久av| 98精品国产自产在线观看| 亚洲第一精品夜夜躁人人躁| 日韩在线激情视频| 97成人精品视频在线观看| 91久久国产综合久久91精品网站| 亚洲欧美日韩一区二区三区在线| 亚洲毛茸茸少妇高潮呻吟| 97精品国产97久久久久久免费| 国产精品久久久久免费a∨大胸| 91香蕉电影院| 欧美成人免费小视频| 欧美精品videosex牲欧美| 久久五月天色综合| 久久精品成人欧美大片| 国产精品高潮视频| 欧美福利小视频| 国产精品国产自产拍高清av水多| 欧美激情综合色综合啪啪五月| 欧美激情手机在线视频| 久久国产精品免费视频| 亚洲一区二区精品| 中文字幕不卡在线视频极品| 国产欧美一区二区白浆黑人| 国产精品激情自拍| 精品国内自产拍在线观看| 久久久久久91香蕉国产| 日韩av在线网| 国产精品福利无圣光在线一区| 欧美日韩激情视频8区| 欧美午夜精品在线| 亚洲国产日韩欧美在线动漫| 成人日韩在线电影| 欧美性生交xxxxx久久久| 日韩中文视频免费在线观看| 日本视频久久久| 亚洲午夜未满十八勿入免费观看全集| 亚洲精品理论电影| 97人人做人人爱| 欧美日韩性生活视频| 欧美午夜丰满在线18影院|