嗯,每當我們在本地系統中工作時,一切都像黃油一樣工作。這就是為什麼我們稱「沒有比 127.0.0.1 更好的地方了」,但醒來面對現實
生產中的事情並不總是按預期進行。大多數情況下,當您執行應用程式的多個實例時。
?正如您所看到的,如果我們的應用程式的多個執行個體正在運行,並且假設我們的客戶端發出請求,將使用者標記為資料庫中的付費使用者。
看起來還不錯吧?到目前為止沒問題吧。
嗯,是的,到目前為止沒有問題。但是如果我們想寫這樣的業務邏輯怎麼辦:-
⚡️ 眾所周知(假設我們在這裡使用 MySQL)MySQL 資料庫符合 ACID,這意味著任何查詢都將是原子的和隔離的。這意味著 MySQL 查詢將以原子方式運行,要么通過,要么失敗。但中間不會退出。
?但這裡有一個問題。想想,想想…
如果在第 2 步,又一個取消付款的請求,然後該查詢首先運行並將用戶標記為免費,然後運行第 3 步並將用戶標記為已付費,會發生什麼情況。
??萬歲,使用者甚至無需付費即可存取我們的產品。
✅救星Locks來了
?鎖是一種結構,一次只允許一個執行緒進入臨界區(不應被多個工作執行緒存取的程式碼區塊)
因此,我們將在操作完成之前取得鎖定並在操作完成後釋放:-
現在,問題來了,如果我們使用一些記憶體鎖資料結構或任何基於記憶體的鎖,它將有資格獲得我們應用程式的一個實例。其他運行相同程式碼並在資料庫中更新的實例怎麼樣?
分散式鎖的概念來了
這裡的鎖充當一種集中式服務,如果我們服務的一個實例取得了鎖,那麼其他實例就無法使用同一個金鑰。
支付服務中可以使用什麼鍵?
?對於進行付款的用戶,金鑰可以是=“PAYMENT_”+ user_id + amount
的組合這對每個使用者來說都是唯一的。並且當用戶付款或取消付款時,該密鑰將保持不變。因此,當一個操作發生時,其他操作無法繼續,因為這兩個操作將嘗試取得相同鍵。
? Key、取得鎖、釋放鎖到底是什麼?最重要的是,redis 是如何使用的?
但是單一 Redis 實例存在以下幾個問題:-
?因此,如果在主伺服器上取得了鎖,並且在與副本通訊時,如果主伺服器在與副本同步之前發生故障。副本將成為主伺服器,其中相同金鑰上的鎖將可用於取得先前在主伺服器上取得的鎖。
即使有兩個實例(主副本),我們服務的兩個實例也將能夠取得 Redis 上的鎖。
取得鎖定:- 我們將嘗試在具有鎖定過期時間的多個 Redis 實例上取得鎖定
鎖定驗證:- 如果主要 Redis 實例為客戶端取得了鎖,則將被視為已取得鎖定
釋放鎖定:- 釋放鎖定時,所有實例都釋放鎖定
是的,就是這樣。
❤️ 感謝您的閱讀,並訂閱我們的時事通訊以獲取更多此類文章:- https://www.serversidedigest.com/
欲了解更多:-
以上是如何使用Redis實現分散式鎖的詳細內容。更多資訊請關注PHP中文網其他相關文章!