可以干什么
分布式锁、分布式对象、分布式集合
防止死锁
设置可重入锁
配置redisson
// 默认连接地址 127.0.0.1:6379
RedissonClient redisson = Redisson.create();
Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
RedissonClient redisson = Redisson.create(config);
简单使用redisson:Lock
今天没时间 写代码测试:先学习一下结论
大概看一下有那些redisson给我们提供了那些锁
基本都是我们Java中JUC中的Lock的类型
说实话 官方比我讲的好(哈哈哈)
可重入锁
说一下什么是死锁
以redis讲 :当一个线程获得了这把锁,执行业务服务代码。然后服务突然宕机,redis中存的key一直没销毁。第二线程试图去获取当前这把锁,发现那个key一直存在就一直在哪等待!
2022-7-29
实战开始
添加依赖
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.16.6</version>
</dependency>
加添配置
我本地reids
先结论
业务超长 自动续期
默认是30秒的过期时间
阻塞等待lock.lock(); 自动续期
lock.lock(11,TimeUnit.SECONDS); 没有看门狗自动续期
看门狗续期源码源码:
首先说为啥说:默认30秒(你在上锁的时候自动构造一个锁对象) 源码:挺深的
public RedissonBaseLock(CommandAsyncExecutor commandExecutor, String name) {
super(commandExecutor, name);
this.commandExecutor = commandExecutor;
this.id = commandExecutor.getConnectionManager().getId();
默认是30秒的过期时间
this.internalLockLeaseTime = commandExecutor.getConnectionManager().getCfg().getLockWatchdogTimeout();
this.entryName = this.id + ":" + name;
}
public long getLockWatchdogTimeout() {
return this.lockWatchdogTimeout;
}
public Config() {
this.transportMode = TransportMode.NIO;
// 这是上锁后默认 30秒
this.lockWatchdogTimeout = 30000L;
this.reliableTopicWatchdogTimeout = TimeUnit.MINUTES.toMillis(10L);
this.keepPubSubOrder = true;
this.useScriptCache = false;
this.minCleanUpDelay = 5;
this.maxCleanUpDelay = 1800;
this.cleanUpKeysAmount = 100;
this.nettyHook = new DefaultNettyHook();
this.useThreadClassLoader = true;
this.addressResolverGroupFactory = new DnsAddressResolverGroupFactory();
}
看门狗续期源码
private void renewExpiration() {
RedissonBaseLock.ExpirationEntry ee = (RedissonBaseLock.ExpirationEntry)EXPIRATION_RENEWAL_MAP.get(this.getEntryName());
if (ee != null) {
Timeout task = this.commandExecutor.getConnectionManager().newTimeout(new TimerTask() {
public void run(Timeout timeout) throws Exception {
RedissonBaseLock.ExpirationEntry ent = (RedissonBaseLock.ExpirationEntry)RedissonBaseLock.EXPIRATION_RENEWAL_MAP.get(RedissonBaseLock.this.getEntryName());
if (ent != null) {
Long threadId = ent.getFirstThreadId();
if (threadId != null) {
RFuture<Boolean> future = RedissonBaseLock.this.renewExpirationAsync(threadId);
future.onComplete((res, e) -> {
if (e != null) {
RedissonBaseLock.log.error("Can't update lock " + RedissonBaseLock.this.getRawName() + " expiration", e);
RedissonBaseLock.EXPIRATION_RENEWAL_MAP.remove(RedissonBaseLock.this.getEntryName());
} else {
if (res) {
RedissonBaseLock.this.renewExpiration();
} else {
RedissonBaseLock.this.cancelExpirationRenewal((Long)null);
}
}
});
}
}
}
internalLockLeaseTime - 这个成员变量:就是刚构造对象构造出来的30s
怎么续期 30s/3s=10s 10秒自动续期
}, this.internalLockLeaseTime / 3L, TimeUnit.MILLISECONDS);
ee.setTimeout(task);
}
}
记性不好了 学了忘 忘了学
lock.lock(11,TimeUnit.SECONDS); 说一下为什么没有看门狗自动续期
没有续期的代码
<T> RFuture<T> tryLockInnerAsync(long waitTime, long leaseTime, TimeUnit unit, long threadId, RedisStrictCommand<T> command) {
return this.evalWriteAsync(this.getRawName(), LongCodec.INSTANCE, command, "if (redis.call('exists', KEYS[1]) == 0) then redis.call('hincrby', 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.getRawName()), new Object[]{unit.toMillis(leaseTime), this.getLockName(threadId)});
}
读写锁
读锁随时可读,写锁悲观锁-独占锁
信号量:
就是限量 操作~~~ 控制好总量 其他请求过来拒绝或者是报错
闭锁
放假校门锁门:大一新生 走 大二走 大三走 大四走 学校才能锁门