一蛀缝、代碼實(shí)現(xiàn)
1.引入依賴
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.8.2</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.8.2</version>
</dependency>
2.創(chuàng)建一個(gè) redisson-config.yml 文件
#Redisson配置
singleServerConfig:
address: "redis://127.0.0.1:6379"
password: xxxx
clientName: null
database: 7 #選擇使用哪個(gè)數(shù)據(jù)庫(kù)0~15
idleConnectionTimeout: 10000
pingTimeout: 1000
connectTimeout: 10000
timeout: 3000
retryAttempts: 3
retryInterval: 1500
reconnectionTimeout: 3000
failedAttempts: 3
subscriptionsPerConnection: 5
subscriptionConnectionMinimumIdleSize: 1
subscriptionConnectionPoolSize: 50
connectionMinimumIdleSize: 32
connectionPoolSize: 64
dnsMonitoringInterval: 5000
#dnsMonitoring: false
threads: 0
nettyThreads: 0
codec:
class: "org.redisson.codec.JsonJacksonCodec"
transportMode: "NIO"
3.創(chuàng)建配置類 RedissonConfig 用于讀取配置文件
/**
* 添加Redisson的配置參數(shù)讀取類RedissonConfig
*/
@Configuration
public class RedissonConfig {
@Bean
public RedissonClient redisson() throws IOException {
// 本例子使用的是yaml格式的配置文件暇藏,讀取使用Config.fromYAML,如果是Json文件靴迫,則使用Config.fromJSON
Config config = Config.fromYAML(RedissonConfig.class.getClassLoader().getResource("redisson-config.yml"));
return Redisson.create(config);
}
}
4.創(chuàng)建工具類 DistributedRedisLock
@Component
public class DistributedRedisLock {
@Autowired
private RedissonClient redissonClient;
private static final String LOCK_TITLE = "redisLock_";
//加鎖
public boolean acquire(String lockName){
//聲明key對(duì)象
String key = LOCK_TITLE + lockName;
System.out.println(key);
//獲取鎖對(duì)象
RLock mylock = redissonClient.getLock(key);
//加鎖惕味,并且設(shè)置鎖過(guò)期時(shí)間,防止死鎖的產(chǎn)生
mylock.lock(2, TimeUnit.MINUTES);
System.err.println("======lock======"+Thread.currentThread().getName());
//加鎖成功
return true;
}
//鎖的釋放
public void release(String lockName){
//必須是和加鎖時(shí)的同一個(gè)key
String key = LOCK_TITLE + lockName;
//獲取所對(duì)象
RLock mylock = redissonClient.getLock(key);
//釋放鎖(解鎖)
mylock.unlock();
System.err.println("======unlock======"+Thread.currentThread().getName());
}
}
5.調(diào)用工具類中的方法使用鎖(id為一個(gè)參數(shù)玉锌,比如下訂單名挥,就可以用訂單id)
//加鎖
distributedRedisLock.acquire(id);
//業(yè)務(wù)邏輯
//釋放鎖
distributedRedisLock.release(id);
二、原理
底層代碼實(shí)現(xiàn)
<T> RFuture<T> tryLockInnerAsync(long leaseTime, TimeUnit unit, long threadId, RedisStrictCommand<T> command) {
this.internalLockLeaseTime = unit.toMillis(leaseTime);
return this.commandExecutor.evalWriteAsync(this.getName(), LongCodec.INSTANCE, command,
"if (redis.call('exists', KEYS[1]) == 0) then redis.call('hset', KEYS[1], ARGV[2], 1);
redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; if (redis.call('hexists',
KEYS[1], ARGV[2]) == 1) then redis.call('hincrby', KEYS[1], ARGV[2], 1);
redis.call('pexpire', KEYS[1], ARGV[1]);
return nil; end; return redis.call('pttl',
KEYS[1]);", Collections.singletonList(this.getName()), new Object[]{this.internalLockLeaseTime, this.getLockName(threadId)});
}
由redis的Lua腳本實(shí)現(xiàn)