1 基本概念
百度百科:控制分布式系統之間同步訪問共享資源方式。
????????在分布式系統中,常常需要協調他們的動作。如果不同的系統或是同一個系統的不同主機之間共享了一個或一組資源,那么訪問這些資源的時候,往往需要互斥來防止彼此干擾來保證一致性,這個時候,便需要使用到分布式鎖。
?????????在單機環境中可以使用Lock、Synchronized可以處理多線程并發問題可以確保同一時刻只有一個線程能夠訪問或修改共享資源。但是在分布式系統中,各個節點不在一個jvm環境中,進而需要新的技術方案來保證不同節點的一個互斥性。一般可以使用MySQL、Zookeeper、redis等方案,本文介紹redis中redisson的方式。
2 基本要求
1、互斥性:在任何時刻,只能有一個客戶端持有鎖、防止多個客戶端同時訪問共享資源
2、安全性:鎖只能由持有它的客戶端釋放,其他客戶端無法刪除或釋放該鎖
3、可重入:持有鎖的客戶端可以重復進入
4、避免死鎖:即使持有鎖的客戶端發生故障(比如宕機),鎖也能通過超時或者釋放機制被釋放,
????????????????????????避免系統永久阻塞
5、容錯性:在部分節點故障時,鎖服務仍能正常運行,客戶端可以正常獲取和釋放鎖
擴展特性:
?高性能?:獲取和釋放鎖的操作應高效,避免成為系統瓶頸。??
?可重入性?:允許同一客戶端多次獲取同一把鎖,避免自我阻塞。??
?非阻塞性?:如果獲取鎖失敗,客戶端應能立即返回結果,而非長時間等待
3 redisson分布式鎖
3.1 代碼實現
3.1.1 導入jar包
<!-- Redis Starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- Redisson Starter (推薦) --><dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.23.4</version> <!-- 使用最新版本 --></dependency>
3.1.2 配置
application.yml配置
spring:redis:host: localhostport: 6381password: 123456 # 若無密碼可刪除database: 0
?配置類
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;@Component
@ConfigurationProperties(prefix = "spring.redis")
public class RedisConfigData {private String host;private Integer port;private String password;private Integer database;public String getHost() {return host;}public void setHost(String host) {this.host = host;}public Integer getPort() {return port;}public void setPort(Integer port) {this.port = port;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public Integer getDatabase() {return database;}public void setDatabase(Integer database) {this.database = database;}
}
package com.hyq.config;import com.hyq.prefix.RedisConfigData;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class RedissonConfig {@Autowiredprivate RedisConfigData redisConfigData;@Beanpublic RedissonClient redissonClient() {Config config = new Config();// 單節點模式(根據spring.redis.*自動注入配置)config.useSingleServer()// 設置服務器的ip和端口號.setAddress("redis://" + redisConfigData.getHost() + ":" + redisConfigData.getPort())// 密碼.setPassword(redisConfigData.getPassword()).setDatabase(redisConfigData.getDatabase());return Redisson.create(config);}}
?使用RedissonClient獲取分布式鎖,后面通過這個入口查看源碼
// 分布式鎖名稱:myLock
RLock lock = redissonClient.getLock("myLock");
// 嘗試獲取分布式鎖 參數:等待時間 釋放時間 時間單位
if(lock.tryLock(10, -1, TimeUnit.SECONDS)) {System.out.println("獲取鎖成功,");Thread.sleep(10000);// 釋放鎖lock.unlock();
} else {System.out.println("獲取鎖失敗, 已經有人在支付cls");
}
?3.2 底層邏輯圖
在redisson中分布式鎖滿足互斥、可重入、安全、容錯等特性。
底層采用的是Hash存儲結構:key:分布式鎖名稱? field: uuid+線程ID value:重入次數
存儲線程ID主要是為了解決可重入,判斷當前是否是獲取鎖的線程
源碼分析見下節
?
?