回答什么是分布式鎖
分布式鎖相對(duì)他的應(yīng)用場(chǎng)景,即有兩個(gè)線程同時(shí)訪問(wèn)對(duì)數(shù)據(jù)庫(kù)進(jìn)行寫(xiě)的操作,這就需要考慮訪問(wèn)的時(shí)候我們?nèi)绾尾僮?
分布式鎖實(shí)現(xiàn)注意的問(wèn)題
1-可以保證在分布式部署的應(yīng)用集群中,同一個(gè)方法在同一時(shí)間只能被一臺(tái)機(jī)器上的一個(gè)線程執(zhí)行。
2-這把鎖要是一把可重入鎖(避免死鎖)
這里解釋一下什么是重入鎖-可重入就意味著:線程可以進(jìn)入任何一個(gè)它已經(jīng)擁有的鎖所同步著的代碼塊。
場(chǎng)景-線程獲得鎖的時(shí)候宕機(jī)-出現(xiàn)了死鎖
可重入鎖參考-http://www.itdecent.cn/p/007bd7029faf
3-這把鎖最好是一把阻塞鎖(根據(jù)業(yè)務(wù)需求考慮要不要這條)
理想的情況則是; 在線程競(jìng)爭(zhēng)不激烈的情況下,使用自旋鎖也是可重入鎖,競(jìng)爭(zhēng)激烈的情況下使用,阻塞鎖。
因?yàn)樽枞i不會(huì)占用CPU資源
4-有高可用的獲取鎖和釋放鎖功能
5-獲取鎖和釋放鎖的性能要好
實(shí)現(xiàn)分布式鎖-基于數(shù)據(jù)庫(kù)
1-對(duì)表字段做唯一性約束-線程請(qǐng)求-獲取唯一字段-相當(dāng)于拿到了鎖.
2-使用MySQL自帶的排他鎖-在查詢語(yǔ)句后面增加for update,數(shù)據(jù)庫(kù)會(huì)在查詢過(guò)程中給數(shù)據(jù)庫(kù)表增加排他鎖。當(dāng)某條記錄被加上排他鎖之后,其他線程無(wú)法再在該行記錄上增加排他鎖。
場(chǎng)景細(xì)節(jié)參考-http://www.weizijun.cn/2016/03/17/%E8%81%8A%E4%B8%80%E8%81%8A%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81%E7%9A%84%E8%AE%BE%E8%AE%A1/
實(shí)現(xiàn)分布式鎖-基于Redis
線程 A 檢查鎖是否存在(get)–>否–>加鎖(set),在 A 發(fā)起加鎖命令但是還沒(méi)有加鎖成功的時(shí)候,可能線程 B 已經(jīng)完成了set操作,鎖被 B 獲得,但是 A 也發(fā)起了加鎖請(qǐng)求,由于set命令并不檢查 key 的存在,B 的鎖很可能會(huì)被 A 的set操作破壞。
幸運(yùn)的是,redis 提供了另一個(gè)命令setx: 當(dāng)指定的 key 不存在時(shí),設(shè)置 key 的值為指定 value,如果存在,不做任何操作,成功則返回 1,失敗則返回 0。也就是只要命令返回成功,線程就能正確獲得鎖,不需要再做類似get檢查操作。
使用setx可以消除網(wǎng)絡(luò)延遲對(duì)鎖設(shè)置的影響。
鎖釋放的過(guò)程,首先檢查客戶端是否仍然持有該鎖,如果持有,則在事務(wù)中刪除鍵值對(duì),釋放鎖的所有權(quán)。
參考詳細(xì)-http://wecatch.me/blog/2016/08/20/distributed-lock-with-redis/
什么場(chǎng)景使用分布式鎖-Reids
如果是為了效率(efficiency)而使用分布式鎖,允許鎖的偶爾失效,那么使用單Redis節(jié)點(diǎn)的鎖方案就足夠了,簡(jiǎn)單而且效率高。Redlock則是個(gè)過(guò)重的實(shí)現(xiàn)(heavyweight)。
如果是為了正確性(correctness)在很嚴(yán)肅的場(chǎng)合使用分布式鎖,那么不要使用Redlock。它不是建立在異步模型上的一個(gè)足夠強(qiáng)的算法,它對(duì)于系統(tǒng)模型的假設(shè)中包含很多危險(xiǎn)的成分(對(duì)于timing)。而且,它沒(méi)有一個(gè)機(jī)制能夠提供fencing token。那應(yīng)該使用什么技術(shù)呢?Martin認(rèn)為,應(yīng)該考慮類似Zookeeper的方案,或者支持事務(wù)的數(shù)據(jù)庫(kù)。
參考-https://mp.weixin.qq.com/s/JTsJCDuasgIJ0j95K8Ay8w
實(shí)現(xiàn)分布式鎖-基于ZooKeeper
ZooKeeper實(shí)現(xiàn)分布式鎖利用了其臨時(shí)子節(jié)點(diǎn)的如下特性:
在/exclusive_lock節(jié)點(diǎn)下創(chuàng)建臨時(shí)子節(jié)點(diǎn)/exclusive_lock/lock,zk會(huì)保證在所有的客戶端中,最終只有一個(gè)客戶端能夠創(chuàng)建成功,即可以認(rèn)為該客戶端獲得了鎖。同時(shí),雖有沒(méi)有獲取到所得客戶端需要到/exclusive_lock節(jié)點(diǎn)上注冊(cè)一個(gè)子節(jié)點(diǎn)變更的Watcher監(jiān)聽(tīng),以便實(shí)時(shí)監(jiān)聽(tīng)到lock節(jié)點(diǎn)的變更情況。
因?yàn)樵讷@取鎖時(shí),創(chuàng)建的是一個(gè)臨時(shí)節(jié)點(diǎn)/exclusive_lock/lock,因此在如下情況,都有可能釋放鎖:
獲取鎖的機(jī)器發(fā)生宕機(jī),臨時(shí)節(jié)點(diǎn)被zk移除
正常執(zhí)行業(yè)務(wù)邏輯后,客戶端主動(dòng)刪除臨時(shí)節(jié)點(diǎn)
無(wú)論什么情況下,lock節(jié)點(diǎn)被移除,zk都會(huì)通知所有在/exclusive_lock節(jié)點(diǎn)上注冊(cè)了子節(jié)點(diǎn)變更的Watcher監(jiān)聽(tīng)的客戶端。這些客戶端在收到通知后,重新發(fā)起分布式鎖的獲取流程。
詳細(xì)參考-http://www.itdecent.cn/p/83881a79a0c8
? ? ? ? ? ? ? -https://yiqiwuliao.com/post/java/zookeeper-shi-xian-fen-bu-shi-suo
文章嚴(yán)重參考,并且作者詳細(xì)說(shuō)明了各個(gè)解決方案遇到的問(wèn)題和解決思路
https://mp.weixin.qq.com/s?__biz=MzI3NzE0NjcwMg==&mid=2650120465&idx=1&sn=26fefc34e461dac09b87eb577ae064e2&chksm=f36bbc30c41c3526f22ecd2182850e9b0fb146050cef3e7a2940cbb711ddd55384111541697a&mpshare=1&scene=1&srcid=1108yFRXkT2iol2JKikclVWQ#rd