領英中國總裁陸堅:領英沒有減少對中國的投入,還會加大
阿新 • • 發佈:2021-10-15
分散式鎖
1,基於資料庫表實現
機制:在資料庫中建立一個表,表中包含方法名等欄位,並在方法名欄位上建立唯一索引,想要執行某個方法,就使用這個方法名向表中插入資料,成功插入則獲取鎖,執行完成後刪除對應的行資料釋放鎖。
1,首先建立一個 分散式鎖表
DROP TABLE IF EXISTS `distributed_lock`; CREATE TABLE `distributed_lock` ( `distributed_lock_id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主鍵', `method_name` VARCHAR(64) NOTNULL COMMENT '加鎖的方法名', `distributed_lock_desc` VARCHAR(255) NOT NULL COMMENT '備註', `inserted_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, `update_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`distributed_lock_id`), UNIQUE KEY `unique_key_method_name` (`method_name`) USING BTREE ) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='分散式鎖';
2,將要執行的方法名作為引數,儲存到分散式鎖表中
INSERT INTO distributed_lock (distributed_lock_id,method_name, distributed_lock_desc) VALUES (816374617763712,'要加鎖的方法名稱', '描述資訊');
如果可以插入成功,代表獲得了鎖,可以執行操作;邏輯執行完畢後,刪除資料,釋放鎖
DELETE FROM distributed_lock WHERE method_name ='要釋放鎖的方法名稱';
缺點:
1,需要考慮資料的效能以及保證資料庫高可用
2,不具備可重入的特性
3,如果宕機,會造成死鎖
4,獲取不到鎖,直接返回失敗,需要程式碼做迴圈獲取鎖
2,基於Redis實現(redis,redission,redLock,lua指令碼,看門狗機制)
機制:jedis.set(String key, String value, String nx, String px, int time);
引數說明:
key:鎖,保證唯一
value:競爭者的ID,例如執行緒名,釋放鎖的時候需要判斷釋放者是否未該鎖的持有者
nx:SET IF NOT EXIST,即當key不存在時進行set操作;當key已存在則不做任何操作。
px:表示要給當前的鎖設定一個過期時間,防止死鎖
time:key的過期時間
執行set()方法只有兩種結果:
1.當key不存在(沒有鎖),進行加鎖操作,並對鎖設定一個過期時間,同時value為加鎖的執行緒名。
2.已經有鎖存在,不做任何操作。
解鎖:
- 判斷當前解鎖競爭者的執行緒名是否為鎖的持有者,如果不是直接返回失敗,如果是則進入第2步。
- 刪除key,如果刪除成功,返回解鎖成功,否則解鎖失敗。
缺點:
1,死鎖問題
2,不可重入
3,因為設定了過期時間,如果業務執行時間超過過期時間,會自動釋放鎖
4,需要保證redis的高可用
3,基於Zookeeper實現
機制:利用Zookeeper建立臨時有序節點來實現分散式鎖
- 當客戶端來請求時,在鎖空間下面建立一個臨時有序節點。
- 如果當前節點的排序是這個空間下面最小的,則代表加鎖成功,否則加鎖失敗,加鎖失敗後設置Watcher,等待前面節點的通知。
- 當前節點監聽其前面一個節點,如果前面一個節點刪除了就通知當前節點。
- 當解鎖時當前節點通知其後繼節點,並刪除當前節點。
缺點:作者:wxw_wang 出處:https://www.cnblogs.com/chauvet/
需要保證zk的高可用
-------------------------------------------
個性簽名:做一個靈魂有趣的人!
如果覺得這篇文章對你有小小的幫助的話,記得在右下角點個“推薦”哦,博主在此感謝!
萬水千山總是情,打賞一分行不行,所以如果你心情還比較高興,也是可以掃碼打賞博主,哈哈哈(っ•̀ω•́)っ✎⁾⁾!