国产99久久精品_欧美日本韩国一区二区_激情小说综合网_欧美一级二级视频_午夜av电影_日本久久精品视频

最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
當前位置: 首頁 - 科技 - 知識百科 - 正文

基于RedisLua腳本實現的分布式鎖

來源:懂視網 責編:小采 時間:2020-11-09 13:13:35
文檔

基于RedisLua腳本實現的分布式鎖

基于RedisLua腳本實現的分布式鎖:最近項目中需要用到一個分布式的鎖,考慮到基于會話節點實現的zookeeper鎖性能不夠,于是想使用 redis 來實現一個分布式的鎖。看了網上的幾個實現方案后,發現都不夠嚴謹。比如這篇:用Redis實現分布式鎖里面設計的鎖有個最大的問題是鎖的超時值TTL會一直
推薦度:
導讀基于RedisLua腳本實現的分布式鎖:最近項目中需要用到一個分布式的鎖,考慮到基于會話節點實現的zookeeper鎖性能不夠,于是想使用 redis 來實現一個分布式的鎖。看了網上的幾個實現方案后,發現都不夠嚴謹。比如這篇:用Redis實現分布式鎖里面設計的鎖有個最大的問題是鎖的超時值TTL會一直

簡單的說,鎖是一個單一的參考點,多個線程基于它來檢查是否允許訪問資源。例如,一個想寫數據的線程,它必須先檢查是否存在一個寫鎖。如果寫鎖存在,需要等待直到鎖釋放后它才能獲取到屬于它的鎖并執行寫操作。這樣,通過鎖就可以避免多個線程的同時寫造成的數據沖突。

現代的操作系統提供了內置的函數來幫助程序員實現并發控制,例如 flock 函數。但是如果多線程的程序運行在多臺機器上呢?如何在分布式系統下控制對資源的訪問呢?

使用一個中心化的鎖服務

首先,我們需要一個所有線程都可以訪問到的地方來存儲鎖。這個鎖只能存在于一個地方,從而保證只有一個權威的地方可以定義鎖的建立和釋放。

Redis是實現鎖的一個理想的候選方案。作為一個輕量級的內存數據庫,快速,事務性和一致性是選擇redis所為鎖服務的主要原因。

設計鎖

鎖本身是很簡單的,就是redis數據庫中一個簡單的key。建立和釋放鎖,并保證絕對的安全,是這個鎖的設計比較棘手的地方。有兩個潛在的陷阱:

1. 應用程序通過網絡和redis交互,這意味著從應用程序發出命令到redis結果返回之間會有延遲。這段時間內,redis可能正在運行其他的命令,而redis內數據的狀態可能不是你的程序所期待的。如果保證程序中獲取鎖的線程和其他線程不發生沖突?

2. 如果程序在獲取鎖后突然crash,而無法釋放它?這個鎖會一直存在而導致程序進入“餓死”(原文成為“死鎖”,感覺不太準確)。

建立鎖

可能想到的最簡單的方法是“用GET方法檢查鎖,如果鎖不存在,就用SET方式設置一個值”。

這個方法雖然簡單,但是不能保證獨占鎖。回顧前面所說的第1個陷阱:因為在GET和SET操作之間有延遲,我們沒法知道從“發送命令”到“redis服務器返回結果”之間的這段時間內是否有其他線程也去建立鎖。當然,這些都在幾毫秒之內,發生的可能性相當低。但是如果在一個繁忙的環境中運行著大量的并發線程和命令,重疊的可能性并不是微不足道的。

為了解決這個問題,應該用SETNX命令。SETNX消除了GET命令需要等待返回值的問題,SETNX只有在key不存在時才返回成功。這意味著只有一個線程可以成功運行SETNX命令,而其他線程會失敗,然后不斷重試,直到它們能建立鎖。

釋放鎖

一旦線程成功執行了SETNX命令,它就建立了鎖并且可以基于資源進行工作。工作完成后,線程需要通過刪除redis的key來釋放這個鎖,從而允許其他線程能盡快的獲取鎖。

盡管如此,也有需要小心的地方!回顧前面說的第2個陷阱:如果線程crash了,它永遠都不會刪除redis的key,所以這個鎖會一直存在,從而導致“餓死”現象。那么如何避免這個問題呢?

鎖的存活時間

我們可以給鎖加一個存活時間(TTL),這樣一旦TTL超時,這個鎖的key會被redis自動刪除。任何由于線程錯誤而遺留下來的鎖在一個合適的時間之后都會被釋放,從而避免了“餓死”。這純粹是一個安全特性,更有效的方式仍然是確保盡量在線程里面釋放鎖。

可以通過PEXPIRE命令為Redis的key設置TTL,而且線程里可以通過MULTI/EXEC事務的方式在SETNX命令后立即執行,例如:

MULTI
SETNX lock-key
PEXPIRE 10000 lock-key
EXEC

盡管如此,這會產生另外一個問題。PEXPIRE命令沒有判斷SETNX命令的返回結果,無論如何都會設置key的TTL。如果這個地方無法獲取到鎖或有異常,那么多個線程每次想獲取鎖時,都會頻繁更新key的TTL,這樣會一直延長key的TTL,導致key永遠都不會過期。為了解決這個問題,我們需要Redis在一個命令里面處理這個邏輯。我們可以通過Redis腳本的方式來實現。

注意-如果不采用腳本的方式來實現,可以使用Redis 2.6.12之后版本SET命令的PX和NX參數來實現。為了考慮兼容2.6.0之前的版本,我們還是采用腳本的方式來實現。

Redis腳本

由于Redis支持腳本,我們可以寫一個Lua腳本在Redis服務端運行多個Redis命令。應用程序通過一條EVALSHA命令就可以調用被Redis服務端緩存的腳本。這里強大的地方在于你的程序只需要運行一條命令(腳本)就可以以事務的方式運行多個redis命令,還能避免并發沖突,因為一個redis腳本同一時刻只能運行一次。

這是Redis里面一個設置帶TTL的鎖的Lua腳本:

--
-- Set a lock
--
-- KEYS[1] - key
-- KEYS[2] - ttl in ms
-- KEYS[3] - lock content
local key = KEYS[1]
local ttl = KEYS[2]
local content = KEYS[3]
local lockSet = redis.call('setnx', key, content)
if lockSet == 1 then
 redis.call('pexpire', key, ttl)
end
return lockSet

從這個腳本可以很清楚的看到,我們通過在鎖上只運行PEXPIRE命令就解決了前面提到的“無休止的TTL”問題。

Warlock: 一個成熟的基于Redis的分布式鎖

上面我們介紹了基于Redis的鎖的理論,這里有一個用Node.js寫的開源模塊Warlock,通過npm可以獲取。它使用了redis腳本來創建/釋放鎖,用于為緩存,數據庫,任務隊列和其他需要并發的地方提供分布式的鎖服務,詳見Github。


原文中還缺少一個釋放鎖的腳本,如果一直依賴TTL來釋放鎖,效率會很低。Redis的SET操作文檔就提供了一個釋放鎖的腳本:

if redis.call("get", KEYS[1]) == ARGV[1]
then
 return redis.call("del", KEYS[1])
else
 return 0
end

應用程序中只要加鎖的時候指定一個隨機數或特定的value作為key的值,解鎖的時候用這個value去解鎖就可以了。當然,每次加鎖時的value必須要保證是唯一的。

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文檔

基于RedisLua腳本實現的分布式鎖

基于RedisLua腳本實現的分布式鎖:最近項目中需要用到一個分布式的鎖,考慮到基于會話節點實現的zookeeper鎖性能不夠,于是想使用 redis 來實現一個分布式的鎖。看了網上的幾個實現方案后,發現都不夠嚴謹。比如這篇:用Redis實現分布式鎖里面設計的鎖有個最大的問題是鎖的超時值TTL會一直
推薦度:
標簽: 中的 實現 腳本
  • 熱門焦點

最新推薦

猜你喜歡

熱門推薦

專題
Top
主站蜘蛛池模板: 欧美1区二区三区公司 | 另类激情亚洲 | 国产精品成人一区二区 | 国产精品一级 | 一级毛片免费毛片一级毛片免费 | 国产精品毛片久久久久久久 | 欧美精品第一页 | 亚洲欧洲综合 | 草逼电影 | 久久久亚洲欧美综合 | 久久免费精品国产72精品剧情 | 欧美日韩免费电影 | 欧美一区二区三区不卡免费 | 欧美日韩国产专区 | 毛片综合 | 亚洲精品乱码久久久久 | 日韩欧美一区二区在线 | 欧美日韩免费一区二区在线观看 | 国产精品电影一区二区三区 | 国产精品一区在线观看 | 欧美人与动性xxxxx杂性 | 国产va在线播放 | 国产美女视频黄a视频全免费网站 | 久久999| 亚洲午夜久久久久久久久电影网 | 在线看欧美 | 国产不卡在线看 | 河边性xxxxfreexxxxx | 国产毛片一区二区三区 | 欧美激情一区二区三区不卡 | 91欧洲在线视精品在亚洲 | 午夜看大片 | 全免费a级毛片免费看不卡 日本二区在线观看 | 国产精选在线 | 久久福利一区二区 | 亚洲国产一成人久久精品 | 伊人久久精品久久亚洲一区 | 国产成人精品视频一区二区不卡 | 欧美激情视频一区二区三区 | 免费在线观看中文字幕 | 亚洲天码中文字幕第一页 |