日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

公平锁非公平锁的实际使用_3. redisson源码公平锁之队列重排序

發(fā)布時(shí)間:2024/1/23 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 公平锁非公平锁的实际使用_3. redisson源码公平锁之队列重排序 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、看源碼前的一些說(shuō)明

1. 這篇文章的源碼筆記是基于之前的筆記,所以,這里的當(dāng)前時(shí)間假設(shè),客戶端A的過(guò)期時(shí)間,都需要結(jié)合之前的筆記

2. 通過(guò)前幾篇的筆記,現(xiàn)在有客戶端A,B,C三個(gè),假設(shè)此時(shí)時(shí)間已經(jīng)到達(dá)了10:00:36,客戶端C來(lái)進(jìn)行的重新嘗試進(jìn)行加鎖,此時(shí)客戶端B他其實(shí)在這之前不知道可能因?yàn)榫W(wǎng)絡(luò)原因或者是別的什么原因,可能他就是沒(méi)有嘗試過(guò)重新加鎖

3. 參數(shù)說(shuō)明,這些參數(shù)都是Lua腳本中的參數(shù),在閱讀源碼的時(shí)候,方便隨時(shí)回頭過(guò)來(lái)看

KEYS = Arrays.asList(getName(), threadsQueueName, timeoutSetName)KEYS[1] = getName() = 鎖的名字,“anyLock”KEYS[2] = threadsQueueName = redisson_lock_queue:{anyLock},基于redis的數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)的一個(gè)隊(duì)列KEYS[3] = timeoutSetName = redisson_lock_timeout:{anyLock},基于redis的數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)的一個(gè)Set數(shù)據(jù)集合,有序集合,可以自動(dòng)按照你給每個(gè)數(shù)據(jù)指定的一個(gè)分?jǐn)?shù)(score)來(lái)進(jìn)行排序ARGV = internalLockLeaseTime, getLockName(threadId), currentTime + threadWaitTime, currentTimeARGV[1] = 30000毫秒ARGV[2] = UUID:threadIdARGV[3] = 當(dāng)前時(shí)間(10:00:00) + 5000毫秒 = 10:00:05ARGV[4] = 當(dāng)前時(shí)間(10:00:00)

二、代碼剖析

代碼片段一、

  • ?RedissonFairLock

  • 源碼解析中的1、2、3是程序進(jìn)來(lái)的順序,比如1走完后,2才會(huì)走

  • @Override RFuture tryLockInnerAsync(long leaseTime, TimeUnit unit, long threadId, RedisStrictCommand command) { internalLockLeaseTime = unit.toMillis(leaseTime); long currentTime = System.currentTimeMillis(); if (command == RedisCommands.EVAL_NULL_BOOLEAN) { return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, command, // remove stale threads "while true do " + "local firstThreadId2 = redis.call('lindex', KEYS[2], 0);" + "if firstThreadId2 == false then " + "break;" + "end; " + "local timeout = tonumber(redis.call('zscore', KEYS[3], firstThreadId2));" + "if timeout <= tonumber(ARGV[3]) then " + "redis.call('zrem', KEYS[3], firstThreadId2); " + "redis.call('lpop', KEYS[2]); " + "else " + "break;" + "end; " + "end;" + "if (redis.call('exists', KEYS[1]) == 0) and ((redis.call('exists', KEYS[2]) == 0) " + "or (redis.call('lindex', KEYS[2], 0) == ARGV[2])) then " + "redis.call('lpop', KEYS[2]); " + "redis.call('zrem', KEYS[3], ARGV[2]); " + "redis.call('hset', KEYS[1], ARGV[2], 1); " + "redis.call('pexpire', KEYS[1], ARGV[1]); " + "return nil; " + "end; " + "if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then " + "redis.call('hincrby', KEYS[1], ARGV[2], 1); " + "redis.call('pexpire', KEYS[1], ARGV[1]); " + "return nil; " + "end; " + "return 1;", Arrays.asList(getName(), threadsQueueName, timeoutSetName), internalLockLeaseTime, getLockName(threadId), currentTime); } if (command == RedisCommands.EVAL_LONG) { return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, command, // remove stale threads //1. 此時(shí)客戶端C會(huì)進(jìn)入到一個(gè)死循環(huán) "while true do “ //1. 從redisson_lock_queue:{anyLock} 中獲取第一個(gè)元素,應(yīng)該是客戶端B,UUID_02:threadId_02 // 2. 此時(shí)隊(duì)列中就只剩下C了,那么此時(shí)firstThreadId2 = UUID_02:threadId_03 + "local firstThreadId2 = redis.call('lindex', KEYS[2], 0);" + "if firstThreadId2 == false then " + "break;" + "end; “ //1. zscore redisson_lock_timeout:{anyLock} UUID_02:threadId_02 獲取客戶端B的超時(shí)時(shí)間 // 2. zscore redisson_lock_timeout:{anyLock} UUID_03:threadId_03,獲取客戶端C的超時(shí)時(shí)間 + "local timeout = tonumber(redis.call('zscore', KEYS[3], firstThreadId2));” //1. 10:00:30(參考前幾篇筆記中的客戶端B的超時(shí)時(shí)間) <= 10:00:36(假設(shè)的當(dāng)前時(shí)間)?條件是成立的 //2. 10:00:35(參考之前筆記客戶端B的超時(shí)時(shí)間) <= 10:00:36(假設(shè)的當(dāng)前時(shí)間) ? ,條件是成立的 + "if timeout <= tonumber(ARGV[4]) then “ // 1. zrem redisson_lcok_timeout:{anyLock} UUID_02:threadId_02 其實(shí)就是將客戶端B在有序集合中的元素進(jìn)行移除 // 2.zrem redisson_lock_timeout:{anyLock} UUID_03:threadId_03 ,將客戶端C在有序集合中移除 + "redis.call('zrem', KEYS[3], firstThreadId2); // 1. Lpop redisson_lock_queue:{anyLock} 將客戶端B在隊(duì)列中進(jìn)行移除 // 1. 此時(shí)隊(duì)列中就只剩下客戶端C了,然后繼續(xù)進(jìn)行死循環(huán)當(dāng)中 // 2. lpop redisson_lock_queue:{anyLock} 將客戶端C從隊(duì)列中移除 // 2. 此時(shí)隊(duì)列中和有序集合中的的元素都為空,跳出死循環(huán) + "redis.call('lpop', KEYS[2]); " + "else " + "break;" + "end; " + "end;" // 3. 這里的條件是不成立的,因?yàn)榭蛻舳薃還持有這把鎖的 + "if (redis.call('exists', KEYS[1]) == 0) and ((redis.call('exists', KEYS[2]) == 0) " + "or (redis.call('lindex', KEYS[2], 0) == ARGV[2])) then " + "redis.call('lpop', KEYS[2]); " + "redis.call('zrem', KEYS[3], ARGV[2]); " + "redis.call('hset', KEYS[1], ARGV[2], 1); " + "redis.call('pexpire', KEYS[1], ARGV[1]); " + "return nil; " + "end; “ + //3.hexists anyLock UUID_03:threadId_03 = 1 條件是不成立的,因?yàn)榇藭r(shí)隊(duì)列時(shí)空的 "if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then " + "redis.call('hincrby', KEYS[1], ARGV[2], 1); " + "redis.call('pexpire', KEYS[1], ARGV[1]); " + "return nil; " + "end; " + // 3.lindex redisson_lock_timeout:{anyLock} 0 取出隊(duì)列的第一個(gè)元素,肯定是空的 "local firstThreadId = redis.call('lindex', KEYS[2], 0); " + "local ttl; “ + // if 條件不滿足 "if firstThreadId ~= false and firstThreadId ~= ARGV[2] then " + "ttl = tonumber(redis.call('zscore', KEYS[3], firstThreadId)) - tonumber(ARGV[4]);" + "else “ // ttl此時(shí)是anyLock的剩余生存時(shí)間,假設(shè)剩余23000毫秒 + "ttl = redis.call('pttl', KEYS[1]);" + "end; " + // timeout = 23000 + 10:00:36 + 5000 = 10:01:04 "local timeout = ttl + tonumber(ARGV[3]);” + // zadd redisson_lock_timeout:{anyLock} 10:01:04 UUID_03:threadId_03 將客戶端C保存到有序集合中 "if redis.call('zadd', KEYS[3], timeout, ARGV[2]) == 1 then “ + // rpush redisson_lock_queue UUID_03:threadid_03 將客戶端C放入到隊(duì)列中 "redis.call('rpush', KEYS[2], ARGV[2]);" + "end; " + "return ttl;", Arrays.asList(getName(), threadsQueueName, timeoutSetName), internalLockLeaseTime, getLockName(threadId), currentTime + threadWaitTime, currentTime); } throw new IllegalArgumentException();}

    三、總結(jié):

  • 我們可以看到,在一個(gè)客戶端剛剛加鎖之后,其他的客戶端來(lái)爭(zhēng)搶這把鎖,剛開(kāi)始在一定時(shí)間范圍之內(nèi),時(shí)間不要過(guò)長(zhǎng),各個(gè)客戶端是可以按照公平的節(jié)奏,在隊(duì)列和有序集合里面進(jìn)行排序

  • 在一定時(shí)間范圍內(nèi),時(shí)間不要過(guò)長(zhǎng),其實(shí)隊(duì)列里的元素順序是不會(huì)改變的,各個(gè)客戶端重新嘗試加鎖,只不過(guò)是刷新有序集合中的分?jǐn)?shù)(timeout),各個(gè)客戶端的timeout不斷加長(zhǎng),但是整體順序大致還是保持一致的

  • 但是如果客戶端A持有的鎖的時(shí)間過(guò)長(zhǎng),timeout,這個(gè)所謂的排隊(duì)是有timeout,可能會(huì)在while true死循環(huán)中將一些等待時(shí)間過(guò)長(zhǎng)的客戶端從隊(duì)列和有序集合中刪除,一旦刪除過(guò)后,就會(huì)發(fā)生各個(gè)客戶端隨著自己重新嘗試加鎖的時(shí)間次序,重新進(jìn)行一個(gè)隊(duì)列中的重排,也就是排隊(duì)的順序可能會(huì)發(fā)生變化

  • 客戶端跟redis通信的網(wǎng)絡(luò)的一個(gè)問(wèn)題,延遲,各種情況都可能會(huì)發(fā)生

  • 客戶端釋放鎖,釋放鎖之后隊(duì)列中的排隊(duì)的客戶端是如何依次獲取這把鎖的,是按照隊(duì)列里的順序去獲取鎖的

  • 四、加鎖流程圖

    四、寄語(yǔ):

    ================

    如果手機(jī)觀看代碼比較難受,可以看網(wǎng)頁(yè)版本的

    https://www.jianshu.com/p/ba52ce206986

    ================

    總結(jié)

    以上是生活随笔為你收集整理的公平锁非公平锁的实际使用_3. redisson源码公平锁之队列重排序的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 韩产日产国产欧产 | 日韩午夜在线 | 日本免费黄色大片 | 国产又粗又长又硬免费视频 | 亚洲福利视频网站 | 自拍偷拍20p | 国产欧美激情视频 | 两性午夜视频 | 国产精品欧美久久久久天天影视 | 久热精品在线观看 | 欧美视频第二页 | 一级不卡 | 久久久久久电影 | 国产免费看 | ktv做爰视频一区二区 | 老熟妇仑乱一区二区av | 成人做受视频试看60秒 | www夜片内射视频日韩精品成人 | 亚洲爱 | 男女互操视频 | 久久久91精品 | 青青草免费在线视频 | 尤物视频免费观看 | 日韩黄色大片 | 人与禽性7777777 | jizz久久| 第一av| 国产精品美女久久久久图片 | 在线观看黄色动漫 | 日韩草逼 | 精品欧美乱码久久久久久 | 91久久精品国产91久久性色tv | 麻豆短视频在线观看 | 无码人妻丰满熟妇奶水区码 | 色一情一区二区三区 | 女人脱下裤子让男人捅 | 中文字幕无线精品亚洲乱码一区 | 亚洲影院中文字幕 | 国产精品2019 | 97久久久久 | 亚洲视频在线一区二区 | 久久久中文字幕 | 蜜桃精品一区二区 | 亚洲国产婷婷香蕉久久久久久99 | 成人av专区 | 国产一区二区三区视频免费观看 | 天天色棕合合合合合合合 | 久久久久久久久久久av | 69精品人人人人 | 自拍在线视频 | 亚洲自拍av在线 | 国产精品老熟女一区二区 | av影片在线看 | 寡妇激情做爰呻吟 | 男人捅爽女人 | 欧美日韩综合在线 | 国产黄色在线 | 欧美日韩国产一区二区在线观看 | 夜夜撸av | 精品视频在线播放 | 99久久精品一区二区 | 福利视频在线免费观看 | 国产精品久久国产愉拍 | 欧美小视频在线观看 | 亚洲av无码国产精品永久一区 | 黄色av网站网址 | 亚洲色图视频在线观看 | 精品少妇无码av无码专区 | 国产精品久久久久久吹潮 | 日韩欧美精品国产 | 天天操夜夜操夜夜操 | 一级女性全黄久久生活片免费 | 狂野少女电影在线观看国语版免费 | 亚洲女人天堂色在线7777 | 亚洲女则毛耸耸bbw 边吃奶边添下面好爽 | 黄色精品在线观看 | 超碰在线伊人 | 欧美1区2区3区4区 | 日本色www| 国产精品永久免费 | 色婷婷av久久久久久久 | 久久久久亚洲av无码麻豆 | 99久久久久成人国产免费 | 日本久久久久久久久久 | 人妻少妇偷人精品久久性色 | 日韩在线视频中文字幕 | 免费看a级片| 欧美亚洲国产另类 | 欧美黑人巨大xxx极品 | 国产午夜精品在线观看 | 免费在线看黄网站 | 日本一区二区三区视频在线播放 | 玖玖精品国产 | 欧美日韩激情一区二区 | 我爱av好色 | 悠悠色综合网 | 伊人综合影院 | 日本高清三区 | 精品一区二区久久久久蜜桃 |