成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Redisson 分布式鎖源碼之公平鎖加鎖

開發 前端 分布式 Redis
默認的加鎖邏輯是非公平的。在加鎖失敗時,線程會進入 while 循環,一直嘗試獲得鎖,這時候是多線程進行競爭。就是說誰搶到就是誰的。

[[408379]]

前言

默認的加鎖邏輯是非公平的。

在加鎖失敗時,線程會進入 while 循環,一直嘗試獲得鎖,這時候是多線程進行競爭。就是說誰搶到就是誰的。

Redisson 提供了公平鎖機制,使用方式如下:

  1. RLock fairLock = redisson.getFairLock("anyLock"); 
  2. // 最常見的使用方法 
  3. fairLock.lock(); 

下面一起看下公平鎖是如何實現的?

1公平鎖

相信小伙伴們看過前面的文章,已經輕車熟路了,直接定位到源碼方法:RedissonFairLock#tryLockInnerAsync。

好家伙,這一大塊代碼,我截圖也截不完,咱們直接分析 lua 腳本。

PS:雖然咱不懂 lua,但是這一堆堆的 if else 咱們大概還是能看懂的。

因為 debug 發現 command == RedisCommands.EVAL_LONG,所以直接看下面一部分。

這么長,連呼好幾聲好家伙!

先來看看參數都有啥?

  • KEYS[1]:加鎖的名字,anyLock;
  • KEYS[2]:加鎖等待隊列,redisson_lock_queue:{anyLock};
  • KEYS[3]:等待隊列中線程鎖時間的 set 集合,redisson_lock_timeout:{anyLock},是按照鎖的時間戳存放到集合中的;
  • ARGV[1]:鎖超時時間 30000;
  • ARGV[2]:UUID:ThreadId 組合 a3da2c83-b084-425c-a70f-5d9a08b37f31:1;
  • ARGV[3]:threadWaitTime 默認 300000;
  • ARGV[4]:currentTime 當前時間戳。

加鎖隊列和集合是含有大括號的字符串。{XXXX} 是指這個 key 僅使用 XXXX 用來計算 slot 的位置。

2Lua 腳本分析

上面的 lua 腳本是分為幾塊的,咱們分別從不同的角度看下上面代碼的執行。

首次加鎖(Thread1)

第一部分,因為是首次加鎖,所以等待隊列為空,直接 跳出循環。這一部分執行結束。

第二部分:

  1. 當鎖不存在,等待隊列為空或隊首是當前線程,兩個條件都滿足時,進入內部邏輯;
  2. 從等待隊列和超時集合中刪除當前線程,這時候等待隊列和超時集合都是空的,不需要任何操作;
  3. 減少隊列中所有等待線程的超時時間,也不需要任何操作;
  4. 加鎖并設置超時時間。

執行完這里就 return 了。所以后面幾部分就暫時不看了。

相當于下面兩個命令(整個 lua 腳本都是原子的!):

  1. > hset anyLock a3da2c83-b084-425c-a70f-5d9a08b37f31:1 1 
  2. > pexpire anyLock 30000 

Thread2 加鎖

當 Thread1 加鎖完成之后,此時 Thread2 來加鎖。

Thread2 可以是本實例其他線程,也可以是其他實例的線程。

第一部分,雖然鎖被 Thread1 占用了,但是等待隊列是空的,直接跳出循環。

第二部分,鎖存在,直接跳過。

第三部分,線程是否持鎖,沒有持鎖,直接跳過。

第四部分,線程是否在等待隊列中,Thread2 才來加鎖,不在里面,直接跳過。

Thread2 最后會來到這里:

  1. 從線程等待隊列 redisson_lock_queue:{anyLock} 中獲取最后一個線程;
  2. 因為等待隊列是空的,所以直接獲取當前鎖的剩余時間 ttl anyLock;
  3. 組裝超時時間 timeout = ttl + 300000 + 當前時間戳,這個 300000 是默認 60000*5;
  4. 使用 zadd 將 Thread2 放到等待線程有序集合,然后使用 rpush 將 Thread2 再放到等待隊列中。

zadd KEYS[3] timeout ARGV[2]

這里使用 zadd 命令分別放置的是,redisson_lock_timeout:{anyLock},超時時間戳(1624612689520),線程(UUID2:Thread2)。

其中超時時間戳當分數,用來在有序集合中排序,表示加鎖的順序。

Thread3 加鎖

Thread1 占有了鎖,Thread2 在等待,此時線程 3 來了。

獲取 firstThreadId2 此時隊列是有線程的是 UUID2:Thread2。

判斷 firstThreadId2 的分數(超時時間戳)是不是小于當前時間戳:

小于等于則說明超時了,移除 firstThreadId2;

大于,則會進入后續判斷。

第二、三、四部分都不滿足條件。

Thread3 最后也會來到這里:

  1. 從線程等待隊列 redisson_lock_queue:{anyLock} 中獲取最后一個線程;
  2. 最后一個線程存在,且不是自己,則 ttl = lastThreadId 超時時間戳 - 當前時間戳,就是看最后一個線程還有多久超時;
  3. 組裝超時時間 timeout = ttl + 300000 + 當前時間戳,這個 300000 是默認 60000*5,在最后一個線程的超時時間上加上 300000 以及當前時間戳,就是 Thread3 的超時時間戳。
  4. 使用 zadd 將 Thread3 放到等待線程有序集合,然后使用 rpush 將 Thread3 再放到等待隊列中。

3總結

本文主要總結了公平鎖的加鎖邏輯,這里涉及到比較多的 Redis 操作,做一下簡要總結:

  1. Redis Hash 數據結構:存放當前鎖,Redis Key 就是鎖,Hash 的 field 是加鎖線程,Hash 的 value 是 重入次數;
  2. Redis List 數據結構:充當線程等待隊列,新的等待線程會使用 rpush 命令放在隊列右邊;
  3. Redis sorted set 有序集合數據結構:存放等待線程的順序,分數 score 用來是等待線程的超時時間戳。

需要理解的就是這里會額外添加一個等待隊列,以及有序集合。

本文轉載自微信公眾號「程序員小航」,可以通過以下二維碼關注。轉載本文請聯系程序員小航公眾號。

 

責任編輯:武曉燕 來源: 程序員小航
相關推薦

2021-07-01 09:42:08

Redisson分布式

2021-07-02 08:51:09

Redisson分布式鎖公平鎖

2021-07-03 17:45:57

分布式Redisson MultiLock

2021-06-27 21:24:55

RedissonJava數據

2021-07-06 08:37:29

Redisson分布式

2022-08-04 08:45:50

Redisson分布式鎖工具

2022-06-30 08:04:16

Redis分布式鎖Redisson

2021-07-07 07:09:49

Redisson分布式鎖源碼

2021-07-10 10:02:30

ZooKeeperCurator并發

2024-01-02 13:15:00

分布式鎖RedissonRedis

2021-06-28 10:51:55

Redisson分布式鎖Watchdog

2021-07-09 06:48:31

ZooKeeperCurator源碼

2021-07-16 07:57:34

ZooKeeperCurator源碼

2023-08-27 22:13:59

Redisson分布式緩存

2018-07-17 08:14:22

分布式分布式鎖方位

2022-04-14 07:56:30

公平鎖Java線程

2021-09-17 07:51:24

RedissonRedis分布式

2018-11-27 16:17:13

分布式Tomcat

2021-11-26 06:43:19

Java分布式

2021-07-08 09:21:17

ZooKeeper分布式鎖 Curator
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美日韩在线免费观看 | 欧美www在线| 成人一区二区视频 | 一级网站 | 成人一区二 | 日韩福利在线观看 | 国产一区中文字幕 | 91视频18| 国产精品久久久久久久一区二区 | 国产成人aⅴ | 欧美国产一区二区 | 成人av电影免费在线观看 | 国产一区在线免费观看视频 | 日本电影免费完整观看 | 亚洲精品视频在线播放 | 国产成人免费网站 | 日韩av一区二区在线 | 欧美手机在线 | 国产精品久久久久一区二区三区 | 国产精品999| 在线视频国产一区 | 一区二区激情 | 精品在线一区二区三区 | 成人三级网址 | 国产高清精品一区二区三区 | 黄色国产 | 久久精品国产免费看久久精品 | 久久这里只有精品首页 | 精品久久久久久 | 国外成人在线视频 | 一级高清视频 | 色婷婷综合久久久中字幕精品久久 | 成人欧美一区二区三区黑人孕妇 | 亚洲一区二区三区在线 | 国产人成精品一区二区三 | 密室大逃脱第六季大神版在线观看 | 国产精品电影在线观看 | 日韩一区二区在线播放 | 国产日韩欧美中文 | 妹子干综合| 国产午夜精品一区二区三区四区 |