Redisson
Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式服务。
Redisson整合
引入依赖
1 2 3 4 5 6
| <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.12.2</version> </dependency>
|
配置redisson
redisson官方提供了多种方式来配置redisson
程序化配置方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| @Configuration public class MyRedissonConfig {
@Bean(destroyMethod="shutdown") RedissonClient redisson() throws IOException { Config config = new Config(); config.useSingleServer().setAddress("redis://192.168.111.100:6379");
RedissonClient redissonClient = Redisson.create(config); return redissonClient; } }
|
一些小例子
自动续期锁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| @ResponseBody @GetMapping("/hello") public String hello() { RLock lock = redisson.getLock("my-lock");
lock.lock(10, TimeUnit.SECONDS); try { System.out.println("加锁成功,执行业务。。。。" + Thread.currentThread().getId()); Thread.sleep(30000); } catch (Exception e) {
} finally { System.out.println("释放锁。。。。" + Thread.currentThread().getId()); lock.unlock(); } return "hello"; }
|
lock.lock(10, TimeUnit.SECONDS) 在锁时间到了以后。不会自动续期。
如果我们传递了锁的超时时间,就发送给redis执行脚本,进行占锁,默认超时就是我们指定的时间
- 如果我们未指定锁的超时时间,就使用30 * 1000;【lockWatchdogTimeout看门狗的默认时间】
- 只要占锁成功,就会启动一个定时任务【重新给锁设置过期时间,新的过期时间就是看门狗的默认时间】,每隔10s都会自动再次续期,续成30s
internalLockLeaseTime【看门狗时间】 /3 ,10s
lock.lock(30, TimeUnit.SECONDS); 省掉了整个续期操作。手动解锁
读写锁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| @GetMapping("/write") @ResponseBody public String writeValue(){ RReadWriteLock lock = redisson.getReadWriteLock("rw-lock"); String s =""; RLock rLock = lock.writeLock(); try { rLock.lock(); s = UUID.randomUUID().toString(); Thread.sleep(30000); redisTemplate.opsForValue().set("writeValue",s); } catch (InterruptedException e) { e.printStackTrace(); }finally { rLock.unlock(); }
return s; }
@GetMapping("/read") @ResponseBody public String readValue(){ RReadWriteLock lock = redisson.getReadWriteLock("rw-lock"); String s =""; RLock rLock = lock.readLock(); rLock.lock(); try { s = redisTemplate.opsForValue().get("writeValue"); } catch (Exception e) { e.printStackTrace(); }finally { rLock.unlock(); }
return s; }
|
- 读写锁,保证一定能读到最新数据,修改期间,写锁是一个排他锁(互斥锁)。读锁是一个共享锁
- 写锁没释放 读就必须等待
- 读锁 + 读锁:相当于无锁,并发读,只会在redis中记录好,所有当前的读锁。他们都会同时加锁成功
- 写锁 + 读锁:等待写锁释放
- 写锁 + 写锁:阻塞方式
- 读锁 + 写锁:有读锁。写也需要等待
- 总结:只要有写锁的存在,都必须等待
信号锁
基于Redis的Redisson的分布式信号量(Semaphore)Java对象RSemaphore
采用了与java.util.concurrent.Semaphore
相似的接口和用法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
@GetMapping("/park") @ResponseBody public String park() throws InterruptedException { RSemaphore park = redisson.getSemaphore("park"); park.acquire();
return "ok"; }
@GetMapping("/go") @ResponseBody public String go() throws InterruptedException { RSemaphore park = redisson.getSemaphore("park"); park.release();
return "ok"; }
|
缓存数据一致性
双写模式

失效模式

Canal

解决方案
