使用場景:
最近遇到一個account dubbo服務的併發註冊問題,日誌中丟擲了大量的主鍵衝突問題。註冊使用者過程中有多個SQL操作,且這些SQL可以實現單機本地事務。為解決這麼多的日誌異常,那麼如何處理分散式併發的請求呢?
解決方式:
一: cache方式
原子操作CAS來寫快取,多個併發請求同時只有一個能夠寫成功。
a) 非冪等的情況沒有寫成功,則直接返回false。 沒有拿到鎖。
b) 冪等的情況,需要輪詢,三種結果:搶到鎖,沒有鎖輪詢成功,沒有鎖輪詢失敗,根據業務處理。account因為可以保證事務,所以輪詢失敗則直接做註冊。
那麼還有哪些方式可以實現這種分散式請求搶佔功能呢?
二: 藉助資料庫的方式
a) unique key
實現原理:
多個請求同時插入一條記錄,只有一條可以插入成功,拿到鎖的請求處理完則刪掉資料, 沒有拿到鎖的則返回或者選擇輪詢嘗試。
缺點:
1. 非阻塞鎖,立刻返回, 只能輪詢或者返回失敗
2. 應用當機了,誰來釋放鎖
3. 如何實現重入鎖
總結:
我覺得我的場景1和3都不是問題,只要考慮應用當機如何釋放鎖就好了,如果採用定時任務的話,定時任務需要判斷當前時間和這個鎖的鎖定時間如果大於事務的執行時間則刪掉這把鎖。但是刪掉鎖的話當前請求可能只做了一半,其他請求也進來了,就演變成一致性的問題,這就需要分散式事務了。
b) for update
實現原理:
start tran; select * for update 如果成功則立刻返回,如果失敗則會等待,解決了非阻塞鎖的問題,當機也會釋放鎖,重入鎖則不行
三:Redis方式
四: zookeeper