完成redisson分布式锁文档的阅读
This commit is contained in:
@@ -1,3 +1,87 @@
|
|||||||
|
- [Redisson](#redisson)
|
||||||
|
- [配置](#配置)
|
||||||
|
- [编程式配置](#编程式配置)
|
||||||
|
- [yml Configuration](#yml-configuration)
|
||||||
|
- [Common Settings](#common-settings)
|
||||||
|
- [codec](#codec)
|
||||||
|
- [connectionListener](#connectionlistener)
|
||||||
|
- [nettyThreads](#nettythreads)
|
||||||
|
- [transportMode](#transportmode)
|
||||||
|
- [threads](#threads)
|
||||||
|
- [lockWatchdogTimeout](#lockwatchdogtimeout)
|
||||||
|
- [Mode](#mode)
|
||||||
|
- [single instance mode](#single-instance-mode)
|
||||||
|
- [Operation Execution](#operation-execution)
|
||||||
|
- [Async方式](#async方式)
|
||||||
|
- [Redisson Object的公共操作](#redisson-object的公共操作)
|
||||||
|
- [分布式对象](#分布式对象)
|
||||||
|
- [object holder](#object-holder)
|
||||||
|
- [RBucket](#rbucket)
|
||||||
|
- [RBuckets](#rbuckets)
|
||||||
|
- [Binary Stream Holder](#binary-stream-holder)
|
||||||
|
- [BitSet](#bitset)
|
||||||
|
- [AtomicLong](#atomiclong)
|
||||||
|
- [AtomicDouble](#atomicdouble)
|
||||||
|
- [Topic](#topic)
|
||||||
|
- [Reliable Topic](#reliable-topic)
|
||||||
|
- [Topic Pattern](#topic-pattern)
|
||||||
|
- [Bloom Filter](#bloom-filter)
|
||||||
|
- [HyperLogLog](#hyperloglog)
|
||||||
|
- [LongAdder](#longadder)
|
||||||
|
- [DoubleAdder](#doubleadder)
|
||||||
|
- [id generator](#id-generator)
|
||||||
|
- [Json Object Holder](#json-object-holder)
|
||||||
|
- [local cache](#local-cache)
|
||||||
|
- [分布式集合](#分布式集合)
|
||||||
|
- [Map](#map)
|
||||||
|
- [eviction](#eviction)
|
||||||
|
- [local cache](#local-cache-1)
|
||||||
|
- [Map Persistence](#map-persistence)
|
||||||
|
- [read-through策略](#read-through策略)
|
||||||
|
- [write-through(sync)策略](#write-throughsync策略)
|
||||||
|
- [write-behind策略(async)](#write-behind策略async)
|
||||||
|
- [Map Listener](#map-listener)
|
||||||
|
- [LRU/LFU bounded Map](#lrulfu-bounded-map)
|
||||||
|
- [MultiMap](#multimap)
|
||||||
|
- [Set based MultiMap](#set-based-multimap)
|
||||||
|
- [List based MultiMap](#list-based-multimap)
|
||||||
|
- [MultiMap eviction](#multimap-eviction)
|
||||||
|
- [Set](#set)
|
||||||
|
- [eviction](#eviction-1)
|
||||||
|
- [SortedSet](#sortedset)
|
||||||
|
- [ScoredSortedSet](#scoredsortedset)
|
||||||
|
- [LexSortedSet](#lexsortedset)
|
||||||
|
- [List](#list)
|
||||||
|
- [Queue](#queue)
|
||||||
|
- [Deque](#deque)
|
||||||
|
- [Blocking Queue](#blocking-queue)
|
||||||
|
- [Bounded Blocking Queue](#bounded-blocking-queue)
|
||||||
|
- [Blocking Deque](#blocking-deque)
|
||||||
|
- [Blocking Fair Queue](#blocking-fair-queue)
|
||||||
|
- [Blocking Fair Deque](#blocking-fair-deque)
|
||||||
|
- [DelayedQueue](#delayedqueue)
|
||||||
|
- [PriorityQueue](#priorityqueue)
|
||||||
|
- [PriorityDeque](#prioritydeque)
|
||||||
|
- [PriorityBlockingQueue](#priorityblockingqueue)
|
||||||
|
- [PriorityBlockingDeque](#priorityblockingdeque)
|
||||||
|
- [Stream](#stream)
|
||||||
|
- [RingBuffer](#ringbuffer)
|
||||||
|
- [Transfer Queue](#transfer-queue)
|
||||||
|
- [Time Series](#time-series)
|
||||||
|
- [分布式锁和synchronizer](#分布式锁和synchronizer)
|
||||||
|
- [Lock](#lock)
|
||||||
|
- [Fair Lock](#fair-lock)
|
||||||
|
- [MultiLock](#multilock)
|
||||||
|
- [ReadWriteLock](#readwritelock)
|
||||||
|
- [Semaphore](#semaphore)
|
||||||
|
- [PermitExpirableSemaphore](#permitexpirablesemaphore)
|
||||||
|
- [CountDownLatch](#countdownlatch)
|
||||||
|
- [SpinLock](#spinlock)
|
||||||
|
- [FencedLock](#fencedlock)
|
||||||
|
- [Redisson整合Spring Cache](#redisson整合spring-cache)
|
||||||
|
- [spring cache yaml config](#spring-cache-yaml-config)
|
||||||
|
|
||||||
|
|
||||||
# Redisson
|
# Redisson
|
||||||
## 配置
|
## 配置
|
||||||
### 编程式配置
|
### 编程式配置
|
||||||
@@ -1211,4 +1295,295 @@ ts.remove(201908110508);
|
|||||||
|
|
||||||
Collection<String> values = ts.pollFirst(2);
|
Collection<String> values = ts.pollFirst(2);
|
||||||
Collection<String> range = ts.range(201908110501, 201908110508);
|
Collection<String> range = ts.range(201908110501, 201908110508);
|
||||||
```
|
```
|
||||||
|
## 分布式锁和synchronizer
|
||||||
|
### Lock
|
||||||
|
基于Redis的分布式ReentrantLock对象实现了java中的Lock接口。
|
||||||
|
为了防止redisson再获取锁之后崩溃导致永远持有锁,redisson维护了watchdog,当持有锁的redisson实例处于活跃状态时,其会延长锁的时间。默认情况下,redisson的超时时间为30s。
|
||||||
|
在获取锁时可以指定leaseTime,在经过指定时间后锁定的lock会自动被释放。
|
||||||
|
> RLock的行为符合java lock规范,意味着只有锁的持有线程才能对锁进行解锁,否则会抛出IllegalMonitorStateException异常。
|
||||||
|
> 如果想要多个线程对锁资源进行操作,可以考虑使用RSemaphore
|
||||||
|
RLock的使用示例如下:
|
||||||
|
```java
|
||||||
|
RLock lock = redisson.getLock("myLock");
|
||||||
|
|
||||||
|
// traditional lock method
|
||||||
|
lock.lock();
|
||||||
|
|
||||||
|
// or acquire lock and automatically unlock it after 10 seconds
|
||||||
|
lock.lock(10, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
// or wait for lock aquisition up to 100 seconds
|
||||||
|
// and automatically unlock it after 10 seconds
|
||||||
|
boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
|
||||||
|
if (res) {
|
||||||
|
try {
|
||||||
|
...
|
||||||
|
} finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
### Fair Lock
|
||||||
|
fair lock会保证所有线程按请求锁的顺序获取锁,所有等待的线程会被排队,如果有线程died,那么redisson会等5s来等待其返回。
|
||||||
|
fair lock使用如下所示:
|
||||||
|
```java
|
||||||
|
RLock lock = redisson.getFairLock("myLock");
|
||||||
|
|
||||||
|
// traditional lock method
|
||||||
|
lock.lock();
|
||||||
|
|
||||||
|
// or acquire lock and automatically unlock it after 10 seconds
|
||||||
|
lock.lock(10, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
// or wait for lock aquisition up to 100 seconds
|
||||||
|
// and automatically unlock it after 10 seconds
|
||||||
|
boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
|
||||||
|
if (res) {
|
||||||
|
try {
|
||||||
|
...
|
||||||
|
} finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
### MultiLock
|
||||||
|
MultiLock允许对多个锁资源同时执行操作,将多个锁资源视作单个锁资源。
|
||||||
|
MultiLock使用示例如下所示:
|
||||||
|
```java
|
||||||
|
RLock lock1 = redisson1.getLock("lock1");
|
||||||
|
RLock lock2 = redisson2.getLock("lock2");
|
||||||
|
RLock lock3 = redisson3.getLock("lock3");
|
||||||
|
|
||||||
|
RLock multiLock = anyRedisson.getMultiLock(lock1, lock2, lock3);
|
||||||
|
|
||||||
|
// traditional lock method
|
||||||
|
multiLock.lock();
|
||||||
|
|
||||||
|
// or acquire lock and automatically unlock it after 10 seconds
|
||||||
|
multiLock.lock(10, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
// or wait for lock aquisition up to 100 seconds
|
||||||
|
// and automatically unlock it after 10 seconds
|
||||||
|
boolean res = multiLock.tryLock(100, 10, TimeUnit.SECONDS);
|
||||||
|
if (res) {
|
||||||
|
try {
|
||||||
|
...
|
||||||
|
} finally {
|
||||||
|
multiLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
### ReadWriteLock
|
||||||
|
基于Redis的ReadWriteLock实现了java中的ReadWriteLock接口,readlock允许有多个owner,writelock只允许有一个owner。
|
||||||
|
ReadWriteLock的使用示例如下所示:
|
||||||
|
```java
|
||||||
|
RReadWriteLock rwlock = redisson.getReadWriteLock("myLock");
|
||||||
|
|
||||||
|
RLock lock = rwlock.readLock();
|
||||||
|
// or
|
||||||
|
RLock lock = rwlock.writeLock();
|
||||||
|
|
||||||
|
// traditional lock method
|
||||||
|
lock.lock();
|
||||||
|
|
||||||
|
// or acquire lock and automatically unlock it after 10 seconds
|
||||||
|
lock.lock(10, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
// or wait for lock aquisition up to 100 seconds
|
||||||
|
// and automatically unlock it after 10 seconds
|
||||||
|
boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
|
||||||
|
if (res) {
|
||||||
|
try {
|
||||||
|
...
|
||||||
|
} finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
### Semaphore
|
||||||
|
基于Redis的Semaphore和java中的Semaphore类似,可以在使用之前进行初始化,但是初始化不是必须的,可以通过trySetPermits方法初始化permit的数量。
|
||||||
|
semaphore使用示例如下所示:
|
||||||
|
```java
|
||||||
|
RSemaphore semaphore = redisson.getSemaphore("mySemaphore");
|
||||||
|
|
||||||
|
// acquire single permit
|
||||||
|
semaphore.acquire();
|
||||||
|
|
||||||
|
// or acquire 10 permits
|
||||||
|
semaphore.acquire(10);
|
||||||
|
|
||||||
|
// or try to acquire permit
|
||||||
|
boolean res = semaphore.tryAcquire();
|
||||||
|
|
||||||
|
// or try to acquire permit or wait up to 15 seconds
|
||||||
|
boolean res = semaphore.tryAcquire(15, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
// or try to acquire 10 permit
|
||||||
|
boolean res = semaphore.tryAcquire(10);
|
||||||
|
|
||||||
|
// or try to acquire 10 permits or wait up to 15 seconds
|
||||||
|
boolean res = semaphore.tryAcquire(10, 15, TimeUnit.SECONDS);
|
||||||
|
if (res) {
|
||||||
|
try {
|
||||||
|
...
|
||||||
|
} finally {
|
||||||
|
semaphore.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
### PermitExpirableSemaphore
|
||||||
|
基于redis的分布式Semaphore对象,其支持在通过acquire获取信号量时添加lease time参数。
|
||||||
|
对于带lease time的permit,每个permit都通过id标识,并且释放操作也是通过id释放。
|
||||||
|
允许通过addPermits方法增加或减少permits数量。
|
||||||
|
```java
|
||||||
|
RPermitExpirableSemaphore semaphore = redisson.getPermitExpirableSemaphore("mySemaphore");
|
||||||
|
|
||||||
|
semaphore.trySetPermits(23);
|
||||||
|
|
||||||
|
// acquire permit
|
||||||
|
String id = semaphore.acquire();
|
||||||
|
|
||||||
|
// or acquire permit with lease time in 10 seconds
|
||||||
|
String id = semaphore.acquire(10, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
// or try to acquire permit
|
||||||
|
String id = semaphore.tryAcquire();
|
||||||
|
|
||||||
|
// or try to acquire permit or wait up to 15 seconds
|
||||||
|
String id = semaphore.tryAcquire(15, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
// or try to acquire permit with least time 15 seconds or wait up to 10 seconds
|
||||||
|
String id = semaphore.tryAcquire(10, 15, TimeUnit.SECONDS);
|
||||||
|
if (id != null) {
|
||||||
|
try {
|
||||||
|
...
|
||||||
|
} finally {
|
||||||
|
semaphore.release(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
### CountDownLatch
|
||||||
|
基于Redis的分布式CountDownLatch对象和java中的CountDownLatch对象类似,在使用之前,应该通过trySetCount来进行初始化。
|
||||||
|
CountDownLatch的使用示例如下所示:
|
||||||
|
```java
|
||||||
|
RCountDownLatch latch = redisson.getCountDownLatch("myCountDownLatch");
|
||||||
|
|
||||||
|
latch.trySetCount(1);
|
||||||
|
// await for count down
|
||||||
|
latch.await();
|
||||||
|
|
||||||
|
// in other thread or JVM
|
||||||
|
RCountDownLatch latch = redisson.getCountDownLatch("myCountDownLatch");
|
||||||
|
latch.countDown();
|
||||||
|
```
|
||||||
|
### SpinLock
|
||||||
|
由于分布式锁是采用的pub/sub机制,故而当短时间内获取或释放大量的锁时,消息会通过pub/sub channel发送到redis集群中所有的节点。
|
||||||
|
可以通过backoff策略来自旋尝试,从而代替pub/sub channel发送时间,这样可以降低redis集群的网络和cpu负载。
|
||||||
|
```java
|
||||||
|
RLock lock = redisson.getSpinLock("myLock");
|
||||||
|
|
||||||
|
// traditional lock method
|
||||||
|
lock.lock();
|
||||||
|
|
||||||
|
// or acquire lock and automatically unlock it after 10 seconds
|
||||||
|
lock.lock(10, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
// or wait for lock aquisition up to 100 seconds
|
||||||
|
// and automatically unlock it after 10 seconds
|
||||||
|
boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
|
||||||
|
if (res) {
|
||||||
|
try {
|
||||||
|
...
|
||||||
|
} finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
### FencedLock
|
||||||
|
FencedLock使用如下所示:
|
||||||
|
```java
|
||||||
|
RFencedLock lock = redisson.getFencedLock("myLock");
|
||||||
|
|
||||||
|
// traditional lock method
|
||||||
|
Long token = lock.lockAndGetToken();
|
||||||
|
|
||||||
|
// or acquire lock and automatically unlock it after 10 seconds
|
||||||
|
token = lock.lockAndGetToken(10, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
// or wait for lock aquisition up to 100 seconds
|
||||||
|
// and automatically unlock it after 10 seconds
|
||||||
|
Long token = lock.tryLockAndGetToken(100, 10, TimeUnit.SECONDS);
|
||||||
|
if (token != null) {
|
||||||
|
try {
|
||||||
|
// check if token >= old token
|
||||||
|
...
|
||||||
|
} finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
## Redisson整合Spring Cache
|
||||||
|
Redisson提供了基于redis的spring cache实现,每个cache实例都有ttl和maxIdleTime两个参数,配置如下所示:
|
||||||
|
```java
|
||||||
|
@Configuration
|
||||||
|
@ComponentScan
|
||||||
|
@EnableCaching
|
||||||
|
public static class Application {
|
||||||
|
|
||||||
|
@Bean(destroyMethod="shutdown")
|
||||||
|
RedissonClient redisson() throws IOException {
|
||||||
|
Config config = new Config();
|
||||||
|
config.useClusterServers()
|
||||||
|
.addNodeAddress("redis://127.0.0.1:7004", "redis://127.0.0.1:7001");
|
||||||
|
return Redisson.create(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
CacheManager cacheManager(RedissonClient redissonClient) {
|
||||||
|
Map<String, CacheConfig> config = new HashMap<String, CacheConfig>();
|
||||||
|
|
||||||
|
// create "testMap" cache with ttl = 24 minutes and maxIdleTime = 12 minutes
|
||||||
|
config.put("testMap", new CacheConfig(24*60*1000, 12*60*1000));
|
||||||
|
return new RedissonSpringCacheManager(redissonClient, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
cache配置也能从yaml文件中进行读取,示例如下:
|
||||||
|
```java
|
||||||
|
@Configuration
|
||||||
|
@ComponentScan
|
||||||
|
@EnableCaching
|
||||||
|
public static class Application {
|
||||||
|
|
||||||
|
@Bean(destroyMethod="shutdown")
|
||||||
|
RedissonClient redisson(@Value("classpath:/redisson.yaml") Resource configFile) throws IOException {
|
||||||
|
Config config = Config.fromYAML(configFile.getInputStream());
|
||||||
|
return Redisson.create(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
CacheManager cacheManager(RedissonClient redissonClient) throws IOException {
|
||||||
|
return new RedissonSpringCacheManager(redissonClient, "classpath:/cache-config.yaml");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
### spring cache yaml config
|
||||||
|
如下是通过yaml的格式来配置spring cache:
|
||||||
|
```java
|
||||||
|
testMap:
|
||||||
|
ttl: 1440000
|
||||||
|
maxIdleTime: 720000
|
||||||
|
localCacheOptions:
|
||||||
|
invalidationPolicy: "ON_CHANGE"
|
||||||
|
evictionPolicy: "NONE"
|
||||||
|
cacheSize: 0
|
||||||
|
timeToLiveInMillis: 0
|
||||||
|
maxIdleInMillis: 0
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user