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

自省:分布式鎖主動續期的入門級實現

開發 項目管理
如果某個客戶端獲得鎖之后處理時間超過最大約定時間,或者持鎖期間內發生了故障導致無法主動釋放鎖,其持有的鎖也能夠被其他機制正確釋放,并保證后續其它客戶端也能加鎖,整個處理流程繼續正常執行。

?一、背景

在《??# 分布式鎖上-初探??》中有提到一個分布式鎖應具備的功能特點中有避免死鎖這一條:

如果某個客戶端獲得鎖之后處理時間超過最大約定時間,或者持鎖期間內發生了故障導致無法主動釋放鎖,其持有的鎖也能夠被其他機制正確釋放,并保證后續其它客戶端也能加鎖,整個處理流程繼續正常執行。

簡單解釋一下:

  1. 客戶端搶到分布式鎖之后開始執行任務,執行完畢后再釋放分布式鎖。
  2. 持鎖后因客戶端異常未能把鎖釋放,會導致鎖成為永恒鎖。
  3. 為了避免這種情況,在創建鎖的時候給鎖指定一個過期時間。
  4. 到期之后鎖會被自動刪除掉,這個角度看是對鎖資源的一種保護。

二、理還亂?

邏輯看很簡單,也很清晰,但任何事情都有兩面性,自動刪除自然有理,但肯定也有弊端。如果要把鎖的功能做的健壯,總要從不斷地自我質疑、自我反思中,理順思路,尋找答案,我認為這屬于自省式學習,以后也想嘗試這種模式,一起來試試吧:

  • 問題:鎖過期了會被刪掉,可是任務沒結束怎么辦?如果鎖被釋放的時候,任務尚未執行完畢,那就可能導致其它客戶端又搶到鎖,任務被重復執行。
  • 問題:把鎖的過期時間定得長一點?邏輯聽起來沒錯,如果你能確定任務的最大耗時,那沒問題;大部分情況都很難確定任務的最大耗時該是多少。
  • 問題:鎖的過期時間定多長合適?反正會被釋放,過期時間定的足夠長吧;如果鎖使用的頻率很高,加了鎖程序有bug釋放不掉,服務端豈不是要出現大量的垃圾數據?思來想去,對一個健壯的分布式鎖來說,過期時間設置太長了不合適,設置太短了也不合適。
  • 問題:怎么平衡?不長不短,主動延期!持鎖期間,酌情推后鎖的過期時間,以基于Redis的分布式鎖來說,就需要調用 API 重置鎖 key 的過期時間。當前線程持鎖后在執行任務期間不能再調用 API 重試鎖 key 的過期時間。
  • 問題:誰來調用API呢?需要使用其他的線程來執行續期。
  • 問題:給每個鎖配一個線程?可以,如果使用分布式鎖的場景中沒有什么并發,一個客戶端也就那么三兩個鎖同時存在,那就沒問題。每個鎖搶鎖成功后,開啟一個線程,在線程中通過循環給鎖續期。
public void run() {
while (true) {
// 續租
action.run()
}
}
  • 問題:多久執行一次續期?有一些常規處理是續租間隔默認采用過期時間的1/3。若把鎖的過期時間設定為與實際耗時相差不大,這樣通過一兩次續租基本就滿足了大部分的情況。
  • 問題:為什么要觸發一次續期操作呢,這不浪費資源嗎?采用過期時間1/3間隔,若用戶定義鎖3秒過期,那每秒鐘都有一個續期指令,有沒有覺得也不太合適。
  • 問題:要不要避免續期指令太頻繁?避免續期指令太頻繁調用是有必要的,也可以增加一個續期的最小間隔時間,比如最少是5秒。可由用戶自己控制續期周期,沒必要一定要發起續期調用。比如任務執行大多在5秒鐘,那么就把鎖定為7秒,續期時間定在6秒,那么6秒內任務結束了就不用續期,即不必把過期時間定的太長,也不必執行一兩次續期操作。
  • 問題:續租的間隔怎么實現?線程內間隔控制通常是通過 sleep() 方法,稍微精準一點的話,單位使用毫秒。
public void run() {
while (true) {
// 1、間隔
TimeUnit.MILLISECONDS.sleep(sleepTime);
// 2、續租
action.run();
}
}
  • 問題:線程要關閉吧?釋放鎖的時候要主動關閉負責續期的線程,所以線程的循環里要有一個變量來控制退出 while 循環
public void run() {
while (isRunning) {
// 1、間隔
TimeUnit.MILLISECONDS.sleep(sleepTime);
// 2、續租
action.run();
}
}
  • 問題:變量是跨線程訪問,如何保證跨線程的可見性呢?在變量上增加 volatile 關鍵字。
private volatile boolean isRunning = true;

void cancel(){
//控制線程退出
this.isRunning = true;
}
  • 問題:如果續期線程里在 sleep(),那就一直等 sleep() 結束?如果等到 sleep() 結束,就挺浪費資源的
  • 問題:能不能快速結束 sleep() 狀態?可以,通過 interrupt(),需留意,被打斷的時候會拋異常 InterruptedException
void cancel(){
//控制線程退出
this.isRunning = true;
//中斷線程
this.interrupt();
}

到這里,似乎都理順了。

三、新的思考

  • 問題:如果同時有成百上千個鎖呢?同時有成百上千個線程在工作,你若認為沒問題,不存在,那ok,不用繼續看下一篇。
  • 那怎么辦呢?可以用 Executors.newScheduledThreadPool ,里邊有 scheduleAtFixedRate

  • 阿里 Java 代碼規范不允許用Execurots嘛?
  • 圖片

    • 不能用?風險是什么?

    本文轉載自微信公眾號「架構染色」,可以通過以下二維碼關注。轉載本文請聯系【架構染色】公眾號作者。

    責任編輯:武曉燕 來源: 架構染色
    相關推薦

    2024-11-28 15:11:28

    2019-06-19 15:40:06

    分布式鎖RedisJava

    2025-03-31 09:59:11

    2021-02-28 07:49:28

    Zookeeper分布式

    2018-04-03 16:24:34

    分布式方式

    2017-04-13 10:51:09

    Consul分布式

    2017-01-16 14:13:37

    分布式數據庫

    2022-04-08 08:27:08

    分布式鎖系統

    2019-02-26 09:51:52

    分布式鎖RedisZookeeper

    2022-01-06 10:58:07

    Redis數據分布式鎖

    2023-08-21 19:10:34

    Redis分布式

    2021-10-25 10:21:59

    ZK分布式鎖ZooKeeper

    2024-10-09 17:12:34

    2023-09-13 09:52:14

    分布式鎖Java

    2018-04-09 09:15:32

    數據庫DB分布式鎖

    2023-03-01 08:07:51

    2022-10-27 10:44:14

    分布式Zookeeper

    2024-07-29 09:57:47

    2024-10-07 10:07:31

    2024-04-01 05:10:00

    Redis數據庫分布式鎖
    點贊
    收藏

    51CTO技術棧公眾號

    主站蜘蛛池模板: 91成人免费看片 | 中文字幕国产视频 | 激情视频网站 | 一区二区三区中文字幕 | 国产九九精品 | 91视频一区二区 | 国产精品亚洲一区二区三区在线观看 | 久草网站| 婷婷综合五月天 | 久久99这里只有精品 | 免费精品视频在线观看 | 国产乱码精品一区二三赶尸艳谈 | 日韩欧美中文 | www.亚洲视频.com | 羞羞色视频 | 羞羞视频在线免费 | 1204国产成人精品视频 | 国产亚洲精品精品国产亚洲综合 | 91久久久久久久 | 国产高清视频一区二区 | 日韩有码一区二区三区 | xxx视频| 欧美人妇做爰xxxⅹ性高电影 | 国产精品国产三级国产aⅴ中文 | 午夜精品一区二区三区免费视频 | 欧美在线视频免费 | 激情欧美一区二区三区 | 亚洲一区综合 | 怡红院免费的全部视频 | 日日操夜夜操天天操 | 国产精品一区二区视频 | 国产在线aa| 久久久久久久国产精品 | 亚洲精品一区久久久久久 | 亚洲欧美精品在线 | 夜夜精品视频 | 水蜜桃亚洲一二三四在线 | 久久久精品 | 国产欧美日韩在线播放 | 国产区在线 | 欧美一区免费 |