simple-starter-redisson
# 简介
提供 注解简化使用:分布式锁、分布式幂等、分布式限流器
提供 分布式加锁、解锁等服务类
提供 常用的对象缓存的常用操作服务类
提供 CacheManager并配置Cacheable注解常用配置及自定义CacheName对应配置
# 分布式幂等和锁的主要区别
- | 锁 | 分布式幂等 |
---|---|---|
目的 | 保护资源完整性,防止多线程导致数据竞争 | 用于保证操作的一致性,防止重复请求影响系统状态 |
范围 | 同步机制,用于控制对共享资源的并发访问 | 分布式系统设计理念,用于处理分布式系统中的重复请求 |
# 引入依赖
<dependencies>
<dependency>
<groupId>cn.iosd</groupId>
<artifactId>simple-starter-redisson</artifactId>
<version>Version</version>
</dependency>
</dependencies>
2
3
4
5
6
7
# 配置项
simple:
redisson:
#分布式锁 缺省项为false
enabled: true
type: standalone
config:
## 单体模式
standalone:
address: redis://127.0.0.1:6379
password:
database: 0
## 主从模式
masterSlave:
masterAddress: redis://127.0.0.1:6379
slaveAddresses:
- redis://127.0.0.1:6379
password:
database: 0
## 哨兵配置
sentinel:
sentinelMasterName: myMaster
sentinelAddresses:
- redis://127.0.0.1:26379
- redis://127.0.0.2:26379
password:
database: 0
## 集群方式
cluster:
clusterAddresses:
- redis://127.0.0.1:7000
- redis://127.0.0.1:7001
- redis://127.0.0.2:7000
password:
#Cacheable注解自定义配置
cacheable:
#缺省项为false,优先级小于simple.redisson.enabled
enabled: true
config:
#自定义cacheName及过期时间
cacheExpiresAfterFiveMinutes:
ttl: 300000
maxIdleTime: 300000
cacheExpiresAfterTenSecond:
ttl: 10000
maxIdleTime: 10000
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
40
41
42
43
44
45
# 功能项
# 注解
# 分布式幂等
注解: @DistributedIdempotent
# 使用示例
@DistributedIdempotent
@DistributedIdempotent(value = "drp", message = "请求重复!", expireTime = 5)
@DistributedIdempotent(param = "#keyName", includePointMd5 = false, message = "请求重复!", expireTime = 5, executionFinishedUnlock = false)
public Response<?> decrement(String keyName) {
return Response.ok();
}
2
3
4
5
6
7
8
# 各字段说明
- value:key固定值
- param:key动态参数值,支持el表达式,默认为空不拼接(若el获取不到对应值默认:DV)
- includePointMd5:key后缀,是否拼接MD5(从切点获取方法参数和实例字符串生成对象,转为md5)
- message:失败的提示信息
- acquireTimeout:获取锁的最长等待时间 默认0
- expireTime:获取后持有锁的最长时间 默认10
- unit:时间单位 默认秒
- executionFinishedUnlock:是否在业务执行结束后解锁,默认true(false:若干时间内防重复提交功能 true:业务逻辑执行期间内防重复提交功能)
# key说明
includePointMd5为true:前缀+固定值+动态参数值+md5.get()
includePointMd5为true且param不传:前缀+固定值+md5.get()
includePointMd5为false:前缀+固定值+动态参数值
includePointMd5为false且param不传:前缀+固定值
eg:
前缀为 SimpleRI:
SimpleRI:固定值:动态参数值:c5a2e....4a0
SimpleRI:固定值:c5a2e....4a0
SimpleRI:固定值:动态参数值
SimpleRI:固定值
2
3
4
5
6
7
# MD5说明
从切点获取方法参数和实例字符串生成对象,转为md5
生成对象:MethodContext
MethodContext[argMap={keyName=cda6666}, name=public cn.iosd.starter.web.domain.Response<?> cn.iosd.demo.redisson.controller.AnnotationIdempotentController.decrementReqPara(java.lang.String)]
生成md5:
Supplier<String> md5 = () -> DigestUtils.md5DigestAsHex(context.toString().getBytes());
# 解锁说明
executionFinishedUnlock
等于true时: 业务执行结束后解锁:业务逻辑执行期间内防重复提交功能
等于false时:业务执行结束后不解锁,等待自动过期:若干时间内防重复提交功能
2
# 使用说明
直接使用注解无需为各字段赋值即可保证分布式幂等:
主要原因:默认开启了md5,md5由切点获取方法参数和实例字符串生成
key为 SimpleRI:IC:c5a2e****
2
入参为实体,为实体对象的单个参数(前提参数值不为空,否则生成的key可能重复)保证分布式幂等: 注解字段使用param,并且关闭md5
/**
* key动态参数值,支持el表达式
*
* <pre>
* 1.获取方法参数中的某个值
* void test(String id) => #id
* 2.获取对象参数中的某个值
* void test(Vo vo) => #vo.id
* 3.参数值获取不到,默认为:DV
* void test(String id) => #im
* 4.默认空,不拼接到key中
* </pre>
*/
String param() default "";
2
3
4
5
6
7
8
9
10
11
12
13
14
入参为实体,为实体对象的单个参数(参数值可能为空)保证分布式幂等: 注解字段使用value,param,并且关闭md5
value:key固定值 自定义取值全局唯一
# 分布式锁
注解: @DistributedLock
# 使用示例
@DistributedLock
@DistributedLock(value = "demo", param = "#keyName", leaseTime = 105)
2
3
4
# 各字段说明
- value:key固定值
- param:key动态参数值,支持el表达式,默认为空不拼接(若el获取不到对应值默认:DV)
- includePointMd5:key后缀,是否拼接MD5(从切点获取方法参数和实例字符串生成对象,转为md5)
- leaseTime:锁的有效时间-秒
# key说明
includePointMd5为true:前缀+固定值+动态参数值+md5.get()
includePointMd5为true且param不传:前缀+固定值+md5.get()
includePointMd5为false:前缀+固定值+动态参数值
includePointMd5为false且param不传:前缀+固定值
eg:
前缀为 SimpleRL:
SimpleRL:固定值:动态参数值:c5a2e....4a0
SimpleRL:固定值:c5a2e....4a0
SimpleRL:固定值:动态参数值
SimpleRL:固定值
2
3
4
5
6
7
# MD5说明
如上
# 解锁说明
leaseTime
在获取到锁之后,该锁会在指定的leaseTime时间后自动释放,即锁的持有时间。
如果在这个时间内业务执行完毕,那么在finally块中的lock.unlock()会手动释放锁,如果在这个时间内业务没有执行完毕,锁也会自动释放
2
# 分布式限流器
注解:@DistributedRateLimiter
# 使用示例
@DistributedRateLimiter
@DistributedRateLimiter(type = RateType.PER_CLIENT)
2
3
4
# 各字段说明
- value:key固定值
- param:key动态参数值,支持el表达式,默认为空不拼接(若el获取不到对应值默认:DV)
- includePointMd5:key后缀,是否拼接MD5(从切点获取方法参数和实例字符串生成对象,转为md5)
- rate:速率(即:在有效时间单位内通过的数量)
- rateTime:有效时间 默认1
- timeUnit:时间单位 默认秒
- message:失败提示信息
- type:限流类型 默认全局
# key说明
includePointMd5为true:前缀+固定值+动态参数值+md5.get()
includePointMd5为true且param不传:前缀+固定值+md5.get()
includePointMd5为false:前缀+固定值+动态参数值
includePointMd5为false且param不传:前缀+固定值
eg:
前缀
单客户端 SimpleRRC:
全局 SimpleRRG:
2
3
# MD5说明
如上
# 限流类型
使用org.redisson.api.RateType 区分为单客户端、全局
# 服务类
# 分布式锁服务类
注入使用
@Autowired(required = false)
private RedissonLockService redissonLockService;
2
加锁操作
/**
* 加锁操作 (设置锁的有效时间)
*
* @param lockName 锁名称
* @param leaseTime 锁有效时间-秒
*/
redissonLockService.lock(lockName, leaseTime);
/**
* 加锁操作(tryLock锁,有等待时间)
*
* @param lockName 锁名称
* @param leaseTime 锁有效时间
* @param waitTime 等待时间
*/
redissonLockService.tryLock(lockName, leaseTime, waitTime)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
解锁操作
/**
* 解锁
*
* @param lockName 锁名称
*/
redissonLockService.unlock(lockName);
2
3
4
5
6
# 缓存服务类
注入使用
@Autowired(required = false)
private RedissonCacheService redissonCacheService;
2
常用示例代码
@Operation(summary = "Object-获取")
@GetMapping("/object/{key}")
public Response<PersonVo> getObject(@PathVariable String key) {
return Response.ok(redissonCacheService.getObject(key));
}
@Operation(summary = "Object-保存")
@PostMapping("/object/{key}")
public Response<?> setObject(@PathVariable String key, @RequestBody PersonVo value) {
redissonCacheService.setObject(key, value);
return Response.ok();
}
@Operation(summary = "List-获取")
@GetMapping("/list/{key}")
public Response<List<PersonVo>> getList(@PathVariable String key) {
return Response.ok(redissonCacheService.getList(key));
}
@Operation(summary = "List-保存")
@PostMapping("/list/{key}")
public Response<?> setList(@PathVariable String key, @RequestBody List<PersonVo> value) {
redissonCacheService.setList(key, value);
return Response.ok();
}
@Operation(summary = "Map-获取")
@GetMapping("/map/{key}")
public Response<Map<String, PersonVo>> getMap(@PathVariable String key) {
return Response.ok(redissonCacheService.getMap(key));
}
@Operation(summary = "Map-保存")
@PostMapping("/map/{key}")
public Response<?> setMap(@PathVariable String key, @RequestBody PersonVo value) {
Map save = new HashMap(2);
save.put(key, value);
redissonCacheService.setMap(key, save);
return Response.ok();
}
@Operation(summary = "删除")
@DeleteMapping("/{key}")
public Response<?> delete(@PathVariable("key") String key) {
redissonCacheService.delete(key);
return Response.ok();
}
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
40
41
42
43
44
45
46
47
# 获取Redisson客户端
注入
@Autowired(required = false)
private RedissonManager redissonManager;
2
获取客户端
redissonManager.getRedisson()
# redisson连接类型
支持:standalone、sentinel、cluster、masterSlave
simple:
redisson:
#缺省项为false
enabled: true
type: standalone
config:
## 单体模式
standalone:
address: redis://127.0.0.1:6379
password:
database: 0
## 主从模式
masterSlave:
masterAddress: redis://127.0.0.1:6379
slaveAddresses:
- redis://127.0.0.1:6379
password:
database: 0
## 哨兵配置
sentinel:
sentinelMasterName: myMaster
sentinelAddresses:
- redis://127.0.0.1:26379
- redis://127.0.0.2:26379
password:
database: 0
## 集群方式
cluster:
clusterAddresses:
- redis://127.0.0.1:7000
- redis://127.0.0.1:7001
- redis://127.0.0.2:7000
password:
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
# 使用注解Cacheable
已提供的cacheName及对应过期时间配置
cacheExpiresAfterTenMinutes:缓存时间10分钟
cacheExpiresAfterOneHour:缓存时间60分钟
cacheNeverExpires:未设置缓存失效时间
2
3
可在配置文件中设置自定义cacheName及对应过期时间配置
如下自定义cacheExpiresAfterFiveMinutes:缓存时间5分钟
自定义cacheExpiresAfterTenSecond:缓存时间10秒
例:
simple:
redisson:
enabled: true
type: standalone
config:
## 单体模式
standalone:
address: redis://127.0.0.1:6379
password:
database: 0
#Cacheable注解自定义配置
cacheable:
#缺省项为false,优先级小于simple.redisson.enabled
enabled: true
config:
#自定义cacheName及过期时间
cacheExpiresAfterFiveMinutes:
ttl: 300000
maxIdleTime: 300000
cacheExpiresAfterTenSecond:
ttl: 10000
maxIdleTime: 10000
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
在服务层中使用示例:
@Cacheable(key = "#keyName + 'FiveMinutes'", cacheNames = "cacheExpiresAfterFiveMinutes", condition = "#keyName.length()>2")
public String annotateTestCacheNameFiveMinutes(String keyName) {
log.info("cacheExpiresAfterFiveMinutes:{}", keyName);
return keyName;
}
@Cacheable(key = "#keyName + 'TenSecond'", cacheNames = "cacheExpiresAfterTenSecond", condition = "#keyName.length()>2")
public String annotateTestCacheNameTenSecond(String keyName) {
log.info("cacheExpiresAfterTenSecond:{}", keyName);
return keyName;
}
2
3
4
5
6
7
8
9
10
11