? ? 在高并發(fā)請(qǐng)求的系統(tǒng)中章办,我們知道要控制多個(gè)線程對(duì)資源的并發(fā)訪問锉走,大都會(huì)用synchronize或者lock鎖來實(shí)現(xiàn)同步,但是在分布式應(yīng)用系統(tǒng)中纲菌,要控制一個(gè)事務(wù)的并發(fā)執(zhí)行,需要跨JVM控制并發(fā)疮绷,那就需要用到分布式鎖翰舌。
? ? 分布式鎖的實(shí)現(xiàn)有很多方法,通常情況下只要是各個(gè)分布式應(yīng)用能共同訪問的資源我們都可以用來作分布式鎖冬骚,區(qū)別只是性能椅贱,安全性,可用性等的考慮了只冻,比如數(shù)據(jù)庫(kù)庇麦,緩存服務(wù)以及業(yè)內(nèi)推崇的zookeeper等。
數(shù)據(jù)庫(kù)實(shí)現(xiàn)分布式鎖思路:利用數(shù)據(jù)庫(kù)唯一索引喜德,悲觀鎖等特性山橄。
1,先select沒有數(shù)據(jù)就插入數(shù)據(jù)舍悯,誰(shuí)插入成功誰(shuí)就獲得鎖航棱,通過delete數(shù)據(jù)進(jìn)行釋放鎖,對(duì)于請(qǐng)求量大情況下數(shù)據(jù)庫(kù)性能是瓶頸萌衬。
2饮醇,鎖等待,如果線程未獲得鎖秕豫,則一般需要進(jìn)行重試或者等待鎖釋放朴艰。這種需求則需要推翻1這種釋放鎖的方式,通過for update加鎖混移,commit釋放鎖可以解決此問題祠墅。但隨之而而來的問題是獨(dú)占鎖持有時(shí)間長(zhǎng)的話,占用數(shù)據(jù)庫(kù)連接會(huì)造成連接池占滿的問題歌径。
通過緩存服務(wù)實(shí)現(xiàn)分布式鎖:memcached的add方法饵隙,redis的setnx方法都是原子操作,memcached的問題是內(nèi)存不夠或者宕機(jī)會(huì)丟失數(shù)據(jù)沮脖。redis可以持久化以及故障恢復(fù)金矛,需要注意設(shè)置失效時(shí)間
基于zookeeper瞬時(shí)有序節(jié)點(diǎn)實(shí)現(xiàn)的分布式鎖芯急,大致思想為:每個(gè)客戶端對(duì)某個(gè)功能加鎖時(shí),在zookeeper上的與該功能對(duì)應(yīng)的指定節(jié)點(diǎn)的目錄下驶俊,生成一個(gè)唯一的瞬時(shí)有序節(jié)點(diǎn)娶耍。判斷是否獲取鎖的方式很簡(jiǎn)單,只需要判斷有序節(jié)點(diǎn)中序號(hào)最小的一個(gè)饼酿。當(dāng)釋放鎖的時(shí)候榕酒,只需將這個(gè)瞬時(shí)節(jié)點(diǎn)刪除即可。同時(shí)故俐,其可以避免服務(wù)宕機(jī)導(dǎo)致的鎖無法釋放想鹰,而產(chǎn)生的死鎖問題。
鎖安全性高药版,zk可持久化辑舷,且能實(shí)時(shí)監(jiān)聽獲取鎖的客戶端狀態(tài)。一旦客戶端宕機(jī)槽片,則瞬時(shí)節(jié)點(diǎn)隨之消失何缓,zk因而能第一時(shí)間釋放鎖。性能開銷比較高还栓。