相關知識
分佈式鎖
分佈式鎖是控制分佈式系統之間同步訪問共享資源的一種方式,在分佈式系統中,如果不同的應用之間共享一個或一組資源,那麼訪問這些資源的時候,往往需要互斥來防止彼此干擾來保證一致性,在這種情況下,便需要使用到分佈式鎖。
- 互斥性。在分佈式環境下,同一時間只有一個客戶端能持有鎖。
- 具備鎖失效機制,防止死鎖。例如鎖的持有者在持有鎖期間崩潰而沒有主動解鎖,鎖需要在規定時間後自動失效,以保證後續可用。
- 具備可重入性,防止死鎖。
- 解鈴還須繫鈴人。釋放鎖與加鎖應該為相同客戶端,不能把別人加的鎖給解了。
Redis 分佈式鎖實現原理
實現原理可參考 http://www.redis.cn/topics/distlock.html。
Redis 是單線程的,所以 Redis 命令具有原子性,Redis 提供了以下幾個命令
- setnx,意思是待創建的鍵如果已存在,則創建失敗,否則創建成功,實現互斥性。
- expire,給鍵加上過期時間,實現自動失效機制
- set key value [EX|PX] [NX],可以將上面兩個命令的動作,在這一個命令實現,其中,EX|PX 是過期時間,EX 使用秒,PX 使用毫秒,NX 表示 setnx 的意思
因為鎖的實現中擁有比較、加鎖等一系列操作,為保證原子性,需要引入 Lua 腳本
加鎖流程:
釋放鎖流程
目標
整合 Redis 實現分佈式鎖
操作步驟
添加依賴
引入 Spring Boot Starter 父工程
添加 spring-boot-starter-data-redis 的依賴
添加後的整體依賴如下
配置
編碼
實現一個分佈式鎖,封裝數據及實現
- key:業務鍵
- redisKey:Redis存儲的鍵,在業務鍵上增加一個前綴,等於增加一個命名空間的意思
- value:鍵值,創建時使用UUID生成,釋放時使用該值進行校驗操作人身份
- expire 及 unit:過期時間
驗證
分佈式鎖,需要分佈式環境,所以本例中只是簡單模擬,創建多個測試用例,每一個用例相當於一個應用程序,同時啟動多個用例進行加鎖操作,最終只會有一個加鎖成功。
源碼地址
本章源碼 : https://gitee.com/gongm_24/spring-boot-tutorial.git
參考
https://blog.52itstyle.vip/archives/1264/
擴展
Redis 相關資料
- spring-data-redis文檔: https://docs.spring.io/spring-data/redis/docs/2.0.1.RELEASE/reference/html/#new-in-2.0.0
- Redis 文檔: https://redis.io/documentation
- Redis 中文文檔: http://www.redis.cn/commands.html
閱讀更多 死牛胖子 的文章