基於redis的分佈式鎖二種應用場景

「分佈式鎖」是用來解決分佈式應用中「併發衝突」的一種經常使用手段,實現方式通常有基於zookeeper及基於redis二種。具體到業務場景中,咱們要考慮二種狀況:redis

1、搶不到鎖的請求,容許丟棄(即:忽略)

好比:一些不是很重要的場景,好比「監控數據持續上報」,某一篇文章的「已讀/未讀」標識位更新,對於同一個id,若是併發的請求同時到達,只要有一個請求處理成功,就算成功。併發

用活動圖表示以下:分佈式

基於redis的分佈式鎖二種應用場景

2、併發請求,不論哪一條都必需要處理的場景(即:不容許丟數據)

好比:一個訂單,客戶正在前臺修改地址,管理員在後臺同時修改備註。地址和備註字段的修改,都必須正確更新,這二個請求同時到達的話,若是不借助db的事務,很容易形成行鎖競爭,但用事務的話,db的性能顯然比不上redis輕量。ide

解決思路:A,B二個請求,誰先搶到分佈式鎖(假設A先搶到鎖),誰先處理,搶不到的那個(即:B),在一旁不停等待重試,重試期間一旦發現獲取鎖成功,即表示A已經處理完,把鎖釋放了。這時B就能夠繼續處理了。性能

但有二點要注意:線程

a、須要設置等待重試的最長時間,不然若是A處理過程當中有bug,一直卡死,或者未能正確釋放鎖,B就一直會等待重試,可是又永遠拿不到鎖。blog

b、等待最長時間,必須小於鎖的過時時間。不然,假設鎖2秒過時自動釋放,可是A還沒處理完(即:A的處理時間大於2秒),這時鎖會由於redis key過時「提早」誤釋放,B重試時拿到鎖,形成A,B同時處理。(注:可能有同窗會說,不設置鎖的過時時間,不就完了麼?理論上講,確實能夠這麼作,可是若是業務代碼有bug,致使處理完後沒有unlock,或者根本忘記了unlock,分佈式鎖就會一直沒法釋放。因此綜合考慮,給分佈式鎖加一個「保底」的過時時間,讓其始終有機會自動釋放,更爲靠譜)事務

用活動圖表示以下:it

基於redis的分佈式鎖二種應用場景

用2個線程模擬併發場景,跑起來後,輸出以下:class

基於redis的分佈式鎖二種應用場景

能夠看到T2線程沒搶到鎖,直接拋出了預期的異常。

把44行的註釋打開,即:換成不容許丟數據的模式,再跑一下:

基於redis的分佈式鎖二種應用場景

能夠看到,T1先搶到鎖,而後通過2秒的處理後,鎖釋放,這時T2重試拿到了鎖,繼續處理,最終釋放。

相關文章
相關標籤/搜索