什麼是分布式鎖

2022-03-27 20:52:05 字數 2371 閱讀 1333

什麼是鎖

另外還有文件:

分布式

分布式情況

此處主要指集群模式下,多個相同服務同時開啟.

分布式鎖

單機redis

基本鎖

改進型

setnx與expire不是乙個原子操作,可能執行完setnx該程序就掛了。

當鎖過期後,該程序還沒執行完,可能造成同時多個程序取得鎖。(貌似這個問題目前還沒有很優雅的解決方案)

再改進

步驟

1. 直接呼叫lua指令碼原子setnx同時expire,設定乙個隨機值。 2. 獲取到鎖則執行同步**塊,沒獲取則根據業務場景可以選擇自旋、休眠、或做乙個等待佇列等擁有鎖程序來喚醒(類似synchronize的同步佇列)。 3. 當同步**塊執行完成,先判斷鎖的key是否是自己設定的,如果是則刪除key(可利用lua做成原子操作),不是則表明自己的鎖已經過期,不需要刪除。(這時候就出現了多程序同時有鎖的問題了)

總結

一般情況下直接用setnx加expire就夠了,但從安全性的角度看還是存在一下幾個問題:

單點問題。單機redis只在單機上,如果單機down了,那麼所有需要用分布式鎖的地方均獲取不到鎖,全部阻塞。需要做好降級的處理。

可能出現多程序同時擁有鎖。

redlock

redlock是redis的作者antirez給出的集群模式的redis分布式鎖,它基於n個完全獨立的redis節點(通常情況下n可以設定成5)。

步驟

1. 獲取當前時間(毫秒數)。 2. 按順序依次向n個redis節點執行獲取鎖的操作。獲取鎖的操作與單機鎖一樣。 3. 如果獲取鎖成功的節點數》=n/2+1,則再計算獲取鎖的時間有沒有超過鎖過期時間(可考慮設定乙個必須留多長的時間給**塊執行),如果超過了則認為取鎖失敗。 4. 如果取鎖失敗則應該對所有節點進行釋放鎖的操作。

優化

zookeeper

zookeeper鎖相關基礎知識

zk基本鎖

zk優化

1. 在/lock節點下建立乙個有序臨時節點(ephemeral_sequential)。 2. 判斷建立的節點序號是否最小,如果是最小則獲取鎖成功。不是則取鎖失敗,然後watch序號比本身小的前乙個節點。 3. 當取鎖失敗,設定watch後則等待watch事件到來後,再次判斷是否序號最小。 4. 取鎖成功則執行**,最後刪除本身節點,釋放了鎖。

分布式鎖總結

分布式鎖存在的問題

均可能存在多程序擁有鎖的情況。redis鎖主要是expire時間與**執行時間的問題,zk鎖的問題在於zk是通過心跳監控程序存活狀態,如果程序進行gc pause或者因為網路原因導致很長時間沒與zk聯絡,則將導致zk認為程序已掛,而後鎖自動釋放,而此時程序並未掛任然在執行。

redlock鎖的時間問題。由於redis的expire的實現是通過pexpireat,如果某個節點發生時鐘跳躍,則該節點可能過早釋放鎖導致一系列問題。

解決方案

獲取鎖時提供乙個fencing token(兩種說法,一種說需要有序,一種說隨機值就可以,我覺得隨機值就可以),在程序獲取鎖後對資料進行操作時,資料所在的資源伺服器需要去鎖中檢視當前token,如果token對的才執行,不對則放棄執行。

我覺得對於放棄執行的應該在我們的**塊中增加類似事物的rollback的操作。因此如果資源伺服器拒絕了我們的操作則表明此時起碼已經存在了另外乙個程序擁有鎖了,為了保證資料安全性不能繼續執行,因此需要回滾到執行**塊之前而繼續去競爭鎖。

至於redis鎖的時間問題,antirez說在運維層面是可以控制時鐘跳躍的區間的,只要能控制跳躍區間與expire的比例就沒問題,詳細可看《基於redis的分布式鎖真的安全嗎?》

總結

大多數時候採用zk鎖就好了,沒必要再考慮安全性的問題。其實也可以通過zk鎖+冪等校驗來達到雙層保障。

fencing 機制需要對資料服務進行修改適配,個人覺得沒這個必要吧。。。

什麼是分布式

1,什麼是分布式?任務分解 節點通訊 1 分布式和集群的關係?2 什麼是大型 訪問量 tps qps 資料量 儲存資料量 3 具體場景 第一版應用 第二版 單擊負載越來越高,資料庫伺服器和應用伺服器分離 第三版 應用伺服器做集群 cookie 儲存的是jsessionid concurrentmap...

什麼是分布式

1,什麼是分布式?任務分解 節點通訊 1 分布式和集群的關係?2 什麼是大型 訪問量 tps qps 資料量 儲存資料量 3 具體場景 第一版應用 第二版 單擊負載越來越高,資料庫伺服器和應用伺服器分離 第三版 應用伺服器做集群 cookie 儲存的是jsessionid concurrentmap...

分布式 分布式鎖

本質是利用redis的setnx 方法的特性來加鎖,setnx 即key不存在則設定key,否則直接返回false,要求在分布式系統中使用同乙個redis服務,以下提供兩種解決方案 1 直接使用redistemplate 這其實並不能完全保證高併發下的安全問題,因為可能在鎖過期之後該執行緒尚未執行完...