前言
繼上次樂觀鎖方案之后, 接下來討論冪等性的第二個方案
悲觀鎖方案
鑒于前兩個系列文章的問題和樂觀鎖的缺點(diǎn), 我們又提出了悲觀鎖方案保證接口的冪等性.
回憶一下, 沒有悲觀鎖的方式是這樣的:
有了悲觀鎖的時候:
有幾點(diǎn)討論說明一下:
是不是可以先去查, 查完之后再等修改的時候再鎖, 其實(shí)查詢完加鎖是可以防止并發(fā)修改的, 只能一個一個的修改, 但是不能保證查詢到的是正確的信息, 如果注冊記錄沒有樂觀鎖的情況下, 還是會插入多條.
阻塞鎖和非阻塞鎖的區(qū)別: 非阻塞鎖如果獲取不到就返回失敗, 阻塞鎖獲取不到會嘗試一定的時間或者嘗試一定懂得次數(shù), 到了閾值才會獲取失敗.
可重入鎖和非可重入鎖的區(qū)別: 當(dāng)注冊用戶一再次申請同一個 email 的鎖, 那么如果是不可重入鎖, 就會造成死鎖, 如果是重入鎖, 可以繼續(xù)獲取這個鎖做事情
悲觀鎖的優(yōu)缺點(diǎn)
對于用戶和系統(tǒng)更友好, 如果沖突概率很大的時候, 不會造成數(shù)據(jù)庫過大的壓力和系統(tǒng)報警
悲觀鎖讓代碼編寫邏輯變得簡單了一些, 可以在代碼編寫中假設(shè)自己在單線程內(nèi)編程, 在一些不重要的業(yè)務(wù)場景下甚至可以減少思考樂觀鎖的設(shè)計(jì)
缺點(diǎn)是如果沖突的可能性不高, 會造成性能的缺失
如果純依賴悲觀鎖, 如果集群網(wǎng)絡(luò)不好等極端的情況下可能會導(dǎo)致兩個客戶端獲取鎖
分布式悲觀鎖實(shí)現(xiàn)常見方案
數(shù)據(jù)庫鎖(基于樂觀鎖實(shí)現(xiàn)悲觀鎖)
Redis 等緩存鎖(https://github.com/redisson/redisson)
Zookeeper 鎖(https://curator.apache.org/)
如果有必要的話, 還可以構(gòu)建多級鎖來提高性能并兼顧穩(wěn)定性