??作者主頁(yè):青花鎖 ??簡(jiǎn)介:Java領(lǐng)域優(yōu)質(zhì)創(chuàng)作者??、Java微服務(wù)架構(gòu)公號(hào)作者??
??簡(jiǎn)歷模板、學(xué)習(xí)資料、面試題庫(kù)、技術(shù)互助??文末獲取聯(lián)系方式 ??
系列專欄目錄
[Java項(xiàng)目實(shí)戰(zhàn)] 介紹Java組件安裝、使用;手寫框架等
[Aws服務(wù)器實(shí)戰(zhàn)] Aws Linux服務(wù)器上操作nginx、git、JDK、Vue等
[Java微服務(wù)實(shí)戰(zhàn)] Java 微服務(wù)實(shí)戰(zhàn),Spring Cloud Netflix套件、Spring Cloud Alibaba套件、Seata、gateway、shadingjdbc等實(shí)戰(zhàn)操作
[Java基礎(chǔ)篇] Java基礎(chǔ)閑聊,已出HashMap、String、StringBuffer等源碼分析,JVM分析,持續(xù)更新中
[Springboot篇] 從創(chuàng)建Springboot項(xiàng)目,到加載數(shù)據(jù)庫(kù)、靜態(tài)資源、輸出RestFul接口、跨越問(wèn)題解決到統(tǒng)一返回、全局異常處理、Swagger文檔
[Spring MVC篇] 從創(chuàng)建Spring MVC項(xiàng)目,到加載數(shù)據(jù)庫(kù)、靜態(tài)資源、輸出RestFul接口、跨越問(wèn)題解決到統(tǒng)一返回
[華為云服務(wù)器實(shí)戰(zhàn)] 華為云Linux服務(wù)器上操作nginx、git、JDK、Vue等,以及使用寶塔運(yùn)維操作添加Html網(wǎng)頁(yè)、部署Springboot項(xiàng)目/Vue項(xiàng)目等
[Java爬蟲] 通過(guò)Java+Selenium+GoogleWebDriver 模擬真人網(wǎng)頁(yè)操作爬取花瓣網(wǎng)圖片、bing搜索圖片等
[Vue實(shí)戰(zhàn)] 講解Vue3的安裝、環(huán)境配置,基本語(yǔ)法、循環(huán)語(yǔ)句、生命周期、路由設(shè)置、組件、axios交互、Element-ui的使用等
[Spring] 講解Spring(Bean)概念、IOC、AOP、集成jdbcTemplate/redis/事務(wù)等
系列文章目錄
第一章 Java線程池技術(shù)應(yīng)用
第二章 CountDownLatch和Semaphone的應(yīng)用
第三章 Spring Cloud 簡(jiǎn)介
第四章 Spring Cloud Netflix 之 Eureka
第五章 Spring Cloud Netflix 之 Ribbon
第六章 Spring Cloud 之 OpenFeign
第七章 Spring Cloud 之 GateWay
第八章 Spring Cloud Netflix 之 Hystrix
第九章 代碼管理gitlab 使用
第十章 SpringCloud Alibaba 之 Nacos discovery
第十一章 SpringCloud Alibaba 之 Nacos Config
第十二章 Spring Cloud Alibaba 之 Sentinel
第十三章 JWT
第十四章 RabbitMQ應(yīng)用
第十五章 RabbitMQ 延遲隊(duì)列
Java鎖的分類
分布式鎖框架-Redisson
前言
Redisson 在基于 NIO 的 Netty 框架上,充分的利?了 Redis 鍵值數(shù)據(jù)庫(kù)提供的?系列優(yōu)勢(shì),在Java 實(shí)??具包中常?接?的基礎(chǔ)上,為使?者提供了?系列具有分布式特性的常??具類。使得原本作為協(xié)調(diào)單機(jī)多線程并發(fā)程序的?具包獲得了協(xié)調(diào)分布式多機(jī)多線程并發(fā)系統(tǒng)的能?,??降低了設(shè)計(jì)和研發(fā)?規(guī)模分布式系統(tǒng)的難度。同時(shí)結(jié)合各富特?的分布式服務(wù),更進(jìn)?步簡(jiǎn)化了分布式環(huán)境中程序相互之間的協(xié)作。
1、redisson工作原理
2、看門狗原理
A服務(wù)先運(yùn)行,在運(yùn)行B服務(wù),還沒(méi)釋放A的鎖,A就掛了,會(huì)不會(huì)死鎖呢?
答:沒(méi)有導(dǎo)致死鎖,因?yàn)榈讓佑锌撮T狗機(jī)制
默認(rèn)指定鎖時(shí)間為30s(看門狗時(shí)間)
鎖的自動(dòng)續(xù)期:若是業(yè)務(wù)超長(zhǎng),運(yùn)行期間自動(dòng)給鎖上新的 30s,不用擔(dān)心業(yè)務(wù)時(shí)間過(guò)長(zhǎng),鎖就自動(dòng)過(guò)期
加鎖的業(yè)務(wù)只要運(yùn)行完成,就不會(huì)給當(dāng)前鎖續(xù)期,及時(shí)不手動(dòng)解鎖,鎖默認(rèn)在30s 后自動(dòng)刪除。
3、spring boot與redisson的整合
3.1、添加庫(kù)存服務(wù):
stock-service
3.2、添加依賴
Maven
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- <dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2021.0.4.0</version>
</dependency>-->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.19.1</version>
</dependency>
Gradle
ext {
//set('redissonVersion', "3.19.1")
redissonVersion = "3.19.1"
}
dependencies {
implementation('org.springframework.boot:spring-boot-starter-web') {
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
}
implementation("org.redisson:redisson:${redissonVersion}")
testImplementation('org.springframework.boot:spring-boot-starter-test')
}
3.3、添加配置
3.3.1、單機(jī)
redisson:
addr:
singleAddr:
host: redis://localhost:6379
password: 123456
database: 0
pool-size: 10
3.3.2、集群
redisson:
addr:
cluster:
hosts: redis://47.96.11.185: 6370,...,redis://47.96.11.185:6373
password : 123456
3.3.3、主從
redisson:
addr:
masterAndSlave:
masterhost: redis : //47.96.11.185 : 6370
slavehosts: redis://47.96.11.185: 6371,redis://47.96.11.185:6372
password : 123456
database : 0
3.4、配置RedissonClient
3.4.1、單機(jī)
/**
* 配置RedissonClient
*/
@Configuration
public class RedissonConfig {
@Value("${redisson.addr.singleAddr.host}")
private String host;
@Value("${redisson.addr.singleAddr.password}")
private String password;
@Value("${redisson.addr.singleAddr.database}")
private int database;
@Value("${redisson.addr.singleAddr.pool-size}")
private int poolSize;
@Bean
public RedissonClient redissonClient(){
Config config = new Config();
config.useSingleServer().setAddress(host)
.setPassword(password)
.setDatabase(database)
.setConnectionPoolSize(poolSize)
.setConnectionMinimumIdleSize(poolSize);
return Redisson.create(config);
}
}
3.4.2、集群
/**
* 配置RedissonClient
*/
@Configuration
public class RedissonConfig {
@Value("${redisson.addr.cluster.hosts}")
private String hosts;
@Value("${redisson.addr.cluster.password}")
private String password;
/**
* 集群模式
*
* @return
*/
@Bean
public RedissonClient redissonClient() {
Config config = new Config();
config.useClusterServers().addNodeAddress(hosts.split("[,]"))
.setPassword(password)
.setScanInterval(2000)
.setMasterConnectionPoolSize(10000)
.setSlaveConnectionPoolSize(10000);
return Redisson.create(config);
}
}
3.4.3、集群
/**
* 配置RedissonClient
*/
@Configuration
public class RedissonConfig {
@Value("${redisson.addr.masterAndSlave.masterhost}")
private String masterhost;
@Value("${redisson.addr.masterAndSlave.slavehosts}")
private String slavehosts;
@Value("${redisson.addr.masterAndSlave.password}")
private String password;
@Value("${redisson.addr.masterAndSlave.database}")
private int database;
/**
* 主從模式
*
* @return
*/
@Bean
public RedissonClient redissonClient() {
Config config = new Config();
config.useMasterSlaveServers()
.setMasterAddress(masterhost)
.addSlaveAddress(slavehosts.split("[,]"))
.setPassword(password)
.setDatabase(database)
.setMasterConnectionPoolSize(10000)
.setSlaveConnectionPoolSize(10000);
return Redisson.create(config);
}
}
3.5、Redisson的使用
- 獲取鎖 —— 公平鎖和?公平鎖
// 獲取公平鎖
RLock lock = redissonClient . getFairLock ( skuId );
// 獲取?公平鎖
RLock lock = redissonClient . getLock ( skuId ); - 加鎖 —— 阻塞鎖和?阻塞鎖
// 阻塞鎖(如果加鎖成功之后,超時(shí)時(shí)間為 30s ;加鎖成功開啟看?狗,剩 5s 延?過(guò)期時(shí)間)
lock . lock ();
// 阻塞鎖(如果加鎖成功之后,設(shè)置?定義 20s 的超時(shí)時(shí)間)
lock . lock ( 20 , TimeUnit . SECONDS );
// ?阻塞鎖(設(shè)置等待時(shí)間為 3s ;如果加鎖成功默認(rèn)超時(shí)間為 30s )
boolean b = lock . tryLock ( 3 , TimeUnit . SECONDS );
// ?阻塞鎖(設(shè)置等待時(shí)間為 3s ;如果加鎖成功設(shè)置?定義超時(shí)間為 20s )
boolean b = lock . tryLock ( 3 , 20 , TimeUnit . SECONDS ); - 釋放鎖
lock . unlock (); - 應(yīng)?示例
// 公平?阻塞鎖
RLock lock = redissonClient . getFairLock ( skuId );
boolean b = lock . tryLock ( 3 , 20 , TimeUnit . SECONDS ); - 減庫(kù)存加鎖案例
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.concurrent.TimeUnit;
@RestController
@RequestMapping("/stock")
public class StockController {
@Autowired
private RedissonClient redissonClient;
@GetMapping("/reduceStock")
public void reduceStock(@RequestParam String productId){
// 獲取?公平鎖
RLock lock = this.redissonClient.getLock("stock:" + productId);
// 阻塞鎖(如果加鎖成功之后,設(shè)置?定義 20s 的超時(shí)時(shí)間)
lock.lock(30, TimeUnit.SECONDS);
System.out.println("加鎖成功." + Thread.currentThread().getName());
try {
TimeUnit.SECONDS.sleep(25);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
System.out.println("解鎖成功." + Thread.currentThread().getName());
lock.unlock();
}
}
}
測(cè)試:瀏覽器發(fā)起兩次兩次減庫(kù)存
http://localhost:8099/stock/reduceStock?productId=001文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-803112.html
3.6、aop實(shí)現(xiàn)分布式鎖
3.6.1、定義注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.concurrent.TimeUnit;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DistributeLock {
/**
* 參數(shù)下標(biāo)
* @return
*/
int[] lockIndex() default {-1} ;
/**
* 鎖的等待時(shí)間
* @return
*/
long waitTime() default 3000;
/**
* 時(shí)間單位
* @return
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
}
3.6.2、定義切面
/**
* 定義分布式鎖的切面
*/
@Component
@Aspect
public class DistributeLockAspect {
@Autowired
private RedissonClient redissonClient;
@Around(value = "@annotation(lock)")
public void distibuteLock(ProceedingJoinPoint proceedingJoinPoint, DistributeLock lock){
Signature signature = proceedingJoinPoint.getSignature();
StringBuilder stringBuilder = new StringBuilder();
//方法所屬的類
String declaringTypeName = signature.getDeclaringTypeName();
String name = signature.getName();
stringBuilder.append(declaringTypeName);
stringBuilder.append(name);
//獲取調(diào)用方法的參數(shù)
Object[] args = proceedingJoinPoint.getArgs();
int[] ints = lock.lockIndex();
if(args != null) {
final int length = args.length;
if (length >0) {
//考慮下標(biāo)越界
for (int anInt : ints) {
//把合法下標(biāo)值放到sb
if (anInt >= 0 && anInt < length){
stringBuilder.append(JSON.toJSONString(args[anInt]));
}
}
}
}
//將方法的信息轉(zhuǎn)成md5,作為鎖的標(biāo)識(shí)
String key = SecureUtil.md5(stringBuilder.toString());
//獲取鎖
RLock rLock = redissonClient.getLock(key);
//從注解獲取時(shí)間單位
TimeUnit timeUnit = lock.timeUnit();
//從注解等待時(shí)間
long waitTime = lock.waitTime();
//執(zhí)行業(yè)務(wù)代碼
try {
//加鎖
rLock.tryLock(waitTime,timeUnit);
System.out.println("成功加鎖。" + Thread.currentThread().getName());
proceedingJoinPoint.proceed();
} catch (Throwable e) {
e.printStackTrace();
}finally {
//解鎖
rLock.unlock();
System.out.println("成功解鎖。" + Thread.currentThread().getName());
}
}
}
注解的使用:文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-803112.html
@DistributeLock(lockIndex = {0,1},waitTime = 3,timeUnit = TimeUnit.SECONDS)
到了這里,關(guān)于云原生微服務(wù)之分布式鎖框架 Redisson的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!