redis實現分布式鎖

2021-10-03 00:19:17 字數 3822 閱讀 8742

redis 分布式鎖的實現

思路: 1)、先判斷沒有,2)、再給裡面放值

1、**第一階段;

public

void

hello()

else

}

問題:加鎖的原子性不能保證

解決:使用redis的setnx

2、**第二階段

setnx->set if not exist:原子操作。判斷帶儲存。

public

void

hello()

else

}

問題:如果由於各種問題(未捕獲的異常、斷電等)導致鎖沒釋放。其他人永遠獲取不到鎖。

解決:加個過期時間。

3、**第三階段

public

void

hello()

else

}

問題:剛拿到鎖,機器炸了,沒來得及設定超時。

解決:加鎖和加超時也必須是原子的。

4、**第四階段:

public

void

hello()

else

}

問題:如果業務邏輯超時,導致鎖自動刪除,業務執行完又刪除一遍鎖。至少多個人都獲取到了鎖。

解決:每個執行緒加鎖設定不同的值 刪鎖時對比 保證刪的是自己加的鎖

5、**第五階段。

public

void

hello()

}else

}

問題:我們獲取鎖的時候,鎖的值正在給我們返回。鎖過期。redis刪除了鎖。但是我們拿到了值,而且對比成功(此時此刻正好有人又獲取)。我們還刪除了鎖。至少兩個執行緒又進入同乙個**。

原因:刪鎖不是原子

解決: lua指令碼進行刪除。

string script =

"if redis.

call

('get'

, keys[1]

)== ar**[

1] then

return redis.

call

('del'

, keys[1]

)else

return

0 end";

jedis.

eval

(script, collections.

singletonlist

(key)

, collections.

singletonlist

(token)

);

1、分布式鎖的核心(保證原子性)

加鎖。佔坑一定要是原子的。(判斷如果沒有,就給redis中儲存值)

鎖要自動超時。

解鎖也要原子。

最終的分布式鎖的**:

@lock

public

void

hello()

else

}

redistemplate和jedis客戶端2選一

@autowired

jedispool jedispool;

public

void

incrdistribute()

"+thread.

currentthread()

.getid()

);}else

catch

(interruptedexception e)

",e);}

}}finally

}

@autowired

stringredistemplate redistemplate;

public

void

incrdistribute()

//刪除鎖

string script =

"if redis.call('get', keys[1]) == ar**[1] then return redis.call('del', keys[1]) else return 0 end"

; defaultredisscript

script1 =

newdefaultredisscript

(script,long.

class);

redistemplate.

execute

(script1, arrays.

aslist

("lock"

),token)

; logger.

info

("刪除鎖成功:{}"

+thread.

currentthread()

.getid()

);}else

}

問題:如果業務執行超時 鎖被自動刪除也是個問題 其他執行緒獲取到鎖進來了也是個問題

解決: 使用守護執行緒 守護執行緒做加時操作 保證過期時間夠用 本執行緒業務執行完成後 守護執行緒加時操作自然結束redisson的看門狗監聽也可以

redis實現分布式鎖有各種問題 建議使用redisson

鎖的更多考慮

1)、自旋。

自旋次數。

自旋超時。

2)、鎖設定

鎖粒度;細;記錄級別;

1)、各自服務各自鎖

2)、分析好粒度,不要鎖住無關資料。一種資料一種鎖,一條資料乙個鎖。

3)、鎖型別

使用jedis springboot整合redis

spring.redis.host=192.168.217.130

spring.redis.jedis.pool.max-active=20

spring.redis.jedis.pool.max-idle=5

pom檔案進入jar包

>

>

redis.clientsgroupid

>

>

jedisartifactid

>

>

3.0.1version

>

dependency

>

新增配置類:

package com.xiepanpan.locks.lockstest.config;

import org.springframework.boot.autoconfigure.data.redis.redisproperties;

import org.springframework.context.annotation.bean;

import org.springframework.context.annotation.configuration;

import redis.clients.jedis.jedispool;

import redis.clients.jedis.jedispoolconfig;

/** * @author: xiepanpan

* @date: 2020/2/20

* @description: jedis 配置類

*/@configuration

public

class

jedisconfig

}

分布式鎖 使用Redis實現分布式鎖

關於分布式鎖的實現,我的前一篇文章講解了如何使用zookeeper實現分布式鎖。關於分布式鎖的背景此處不再做贅述,我們直接討論下如何使用redis實現分布式鎖。關於redis,筆主不打算做長篇大論的介紹,只介紹下redis優秀的特性。支援豐富的資料型別,如string list map set zs...

redis實現分布式鎖

隨便 系統越來越大,各功能模組除了垂直切割以外,同時也得做集群處理,那麼問題來了,在多執行緒情況下對於資源的競爭就需要乙個統一的訪問限制。以選課系統為例子,集群中各節點對課程可選數量同時操作,這裡就需要同步了,否則會導致最後選到的數量比可選的數量大,這裡我們的分布式鎖就派上用場了。利用redis來實...

redis實現分布式鎖

分布式鎖可以基於很多種方式實現,比如zookeeper redis.不管哪種方式,他的 基本原理是不變的 用乙個狀態值表示鎖,對鎖的占用和釋放通過狀態值來標識。1 使用redis的setnx命令實現分布式鎖 1 實現的原理 redis為單程序單執行緒模式,採用佇列模式將併發訪問變成序列訪問,且多客戶...