分布式锁闲谈
分布式鎖閑談
前言
服務(wù)器單機(jī)情況下,要鎖住某個資源,我們一般用到的是synchronized,lock等鎖,這是java提供的,也確實能很有效的鎖住資源。
但是在服務(wù)器集群的情況下,上面這些單機(jī)鎖就不起作用了,你能鎖住這臺機(jī)器,但剩下的機(jī)器都沒鎖,就沒有意義。
所以,一般解決這種問題,我們都用分布式鎖。
分布式鎖原理
分布式鎖,主要原理就是新增了一個第三方存儲介質(zhì),代替以前的synchronized。
假設(shè)服務(wù)器A對某個資源加鎖后,就在這個第三方介質(zhì)中記錄,然后其他服務(wù)器再訪問該資源的時候,就能知道這個資源被鎖住了,效果就達(dá)到了。
所以也可以說,這個第三方資源,也可以理解成將服務(wù)器集群強(qiáng)行變成了一個單機(jī)服務(wù)器了。
一般情況下,能擔(dān)當(dāng)這個第三方介質(zhì)的,有以下三種。
1.數(shù)據(jù)庫
2.redis
3.zookeeper
1.數(shù)據(jù)庫
不管集群有幾個服務(wù)器,都會操作一張表
所以,想要加鎖,只需在數(shù)據(jù)庫中插入一條數(shù)據(jù)即可,記錄這個資源的唯一標(biāo)識,狀態(tài)為已加鎖。
再有加鎖的請求,一查數(shù)據(jù)庫已經(jīng)加鎖了,就是沒有獲取到鎖。
一般基于數(shù)據(jù)庫的分布式鎖,都會考慮以下幾個問題
鎖的失效時間(一般做法就是job定時掃,刪掉過期的鎖,但多久才算過期,是一個很值得仔細(xì)研究的問題,一般都是因具體業(yè)務(wù)來定)
數(shù)據(jù)庫的可靠性(這個倒不是主要問題,一般可以通過搭建集群等方式解決)
數(shù)據(jù)庫的效率問題(畢竟數(shù)據(jù)庫是讀磁盤,肯定沒有讀內(nèi)存快)
2.redis
這個應(yīng)該是最常見的,redis分布式鎖。
setNx方法估計很多人都用過,不多說了,set if not exist
舊版本的redis,加鎖和設(shè)置過期時間,但這樣是有問題的,比如加鎖了,但沒有來得及設(shè)置過期時間,服務(wù)掛了,那么這個鎖就死鎖了
新版redis,相當(dāng)于將這兩步合成一個方法了,支持多參數(shù),這就感覺很完美啊,不過我沒用過,可以試試,應(yīng)該沒問題。
一般基于redis的分布式鎖,會考慮以下問題:
鎖的失效問題(和數(shù)據(jù)庫分布式鎖一樣,失效時間設(shè)置多少算最優(yōu),沒有答案,只能job異步掃,一樣的問題,所以不能算是一個優(yōu)雅的解決方案)
鎖是非阻塞的 (成功失敗都會立即返回,這個要看業(yè)務(wù)怎么操作了,也可以在業(yè)務(wù)上手動阻塞住,這不是問題,但要知道)
3.zookeeper
大數(shù)據(jù)高并發(fā),一般用這個
使用臨時有序節(jié)點,服務(wù)器A的方法加鎖就在對應(yīng)方法節(jié)點上創(chuàng)建一個臨時有序節(jié)點,算是獲得鎖,因為第一個創(chuàng)建的,序號最小,所以后面再有其他服務(wù)器想要加鎖時,一查自己的節(jié)點的序號不是最小,所以就算沒有獲得鎖。
因為zookeeper的臨時有序節(jié)點,當(dāng)加鎖的這個線程斷掉后,這個節(jié)點也自動消失,那么鎖也就自動釋放了,是不是感覺特別合適做分布式鎖,上面兩個關(guān)于鎖的失效問題,用zookeeper得到了優(yōu)雅的解決
一般需要注意的是:
zookeeper相對復(fù)雜(zookeeper算是比較重量級的,甚至有些小項目都不會用到zookeeper,所以也沒有必要為了一個簡單的分布式鎖的問題,強(qiáng)行使用zookeeper)
性能問題(一般和redis比性能,都是弟弟)
總結(jié)
在性能方面,redis > zookeeper > 數(shù)據(jù)庫
在實現(xiàn)的復(fù)雜度方面,zookeeper > redis > 數(shù)據(jù)庫
對于新手而言,數(shù)據(jù)庫 > redis > zookeeper
可靠性方面,zookeeper > redis > 數(shù)據(jù)庫
所以,一般項目用redis分布式鎖就可以了,
如果對可靠性要求很高,那么建議考慮zookeeper分布式鎖,
幾乎很少用數(shù)據(jù)庫分布式鎖,主要還是性能問題。
補(bǔ)充
其實分布式鎖就是一個集群環(huán)境如何共享資源的問題,我們看問題的角度不應(yīng)該僅僅停留在分布式鎖這里。很多問題的解決方案,其實都是大同小異的。
比如shiro的集群session共享,一般做法也是放在redis中,其實和這個redis的分布式鎖原理一樣。
還有很多類似場景,歡迎評論補(bǔ)充。
總結(jié)
- 上一篇: CSS串联和后代选择器
- 下一篇: [网络]------长连接和短连接