SchedulerLock 分佈式鎖 原理

背景

使用@SchedulerLock可以實現比較輕量級的簡單的定時任務,也可以實現分佈式鎖,那具體的原理是啥?

一探究竟

不熟悉的同學可以先看一下用法:
https://www.baeldung.com/shedlock-spring

大概就是定義一個數據表
在這裏插入圖片描述
注意這裏的name是primary key,是不可重複的。利用了primary key的這個特性,實現了鎖的搶佔。細節下面會介紹

然後加註解實現:
在這裏插入圖片描述

看源碼

直接從註解出發,看源碼
在註解所在的包內發現一個DefaultLockManager

一看有executeWithTask,應該就是這個代碼了
在這裏插入圖片描述

一直往裏看
在這裏插入圖片描述

doLock
在這裏插入圖片描述

在這裏插入圖片描述

insertRecord,看jdbc的實現
在這裏插入圖片描述

獲取鎖邏輯

其實很簡單,就是一個sql語句

INSERT INTO tableName (name, lock_until, locked_at, locked_by) VALUES(鎖名字, 當前時間+最多鎖多久, 當前時間, 主機名)

如果插入成功了,就說明搶到了鎖。否則認爲搶不到。

如果記錄已經存在了,就用更新記錄來搶鎖
在這裏插入圖片描述

UPDATE  tableName  SET lock_until = 當前時間+最多鎖多久, locked_at = 當前時間, locked_by = 主機名 WHERE name = 鎖名字 AND lock_until <= 當前時間

找到同一個name的鎖,如果發現lock_util小於等於當前時間(鎖已經無效),就可以去update;多個機器同時update,只有一個機器可以update成功(修改行數>0),實現了鎖的搶佔。

釋放鎖邏輯

在這裏插入圖片描述
注:lockTime = 最小鎖時間 和 當前時間的較大值

UPDATE tableName SET lock_until = lockTime WHERE name = 鎖名字

假設最小鎖時間30s,當前時間只過了15s,那麼就會最小鎖時間;否則用當前時間。
這個就是爲了保證最少也要鎖 最小鎖時間 (30s)

總結

SchedulerLock利用mysql實現了分佈式鎖。
搶鎖:
通過插入同一個name(primary key),或者更新同一個name來搶
釋放鎖:
通過設置lock_until來實現釋放,再次搶鎖的時候需要通過lock_util來判斷鎖失效了沒。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章