彻底移除 RedisKeyDefine

This commit is contained in:
YunaiV 2023-07-29 07:16:10 +08:00
parent 95edd1d451
commit 5e7e3d816c
18 changed files with 50 additions and 404 deletions

View File

@ -1,47 +0,0 @@
package cn.iocoder.yudao.framework.tenant.core.redis;
import cn.hutool.core.util.ArrayUtil;
import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import java.time.Duration;
/**
* 多租户拓展的 RedisKeyDefine 实现类
*
* 由于 Redis 不同于 MySQL column 字段无法通过类似 WHERE tenant_id = ? 的方式过滤
* 所以需要通过在 Redis Key 上增加后缀的方式进行租户之间的隔离具体的步骤是
* 1. 假设 Redis Key user:%d示例是 user:1对应到多租户的 Redis Key user:%d:%d
* 2. Redis DAO 需要使用 {@link #formatKey(Object...)} 方法进行 Redis Key 的格式化
*
* 注意大多数情况下并不用使用 TenantRedisKeyDefine 实现主要的使用场景还是 Redis Key 可能存在冲突的情况
* 例如说租户 1 2 都有一个手机号作为 Key则他们会存在冲突的问题
*
* @author 芋道源码
*/
public class TenantRedisKeyDefine extends RedisKeyDefine {
/**
* 多租户的 KEY 模板
*/
private static final String KEY_TEMPLATE_SUFFIX = ":%d";
public TenantRedisKeyDefine(String memo, String keyTemplate, KeyTypeEnum keyType, Class<?> valueType, Duration timeout) {
super(memo, buildKeyTemplate(keyTemplate), keyType, valueType, timeout);
}
public TenantRedisKeyDefine(String memo, String keyTemplate, KeyTypeEnum keyType, Class<?> valueType, TimeoutTypeEnum timeoutType) {
super(memo, buildKeyTemplate(keyTemplate), keyType, valueType, timeoutType);
}
private static String buildKeyTemplate(String keyTemplate) {
return keyTemplate + KEY_TEMPLATE_SUFFIX;
}
@Override
public String formatKey(Object... args) {
args = ArrayUtil.append(args, TenantContextHolder.getRequiredTenantId());
return super.formatKey(args);
}
}

View File

@ -1,27 +0,0 @@
package cn.iocoder.yudao.framework.tenant.core.redis;
import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
class TenantRedisKeyDefineTest {
@Test
public void testFormatKey() {
Long tenantId = 30L;
TenantContextHolder.setTenantId(tenantId);
// 准备参数
TenantRedisKeyDefine define = new TenantRedisKeyDefine("", "user:%d:%d", RedisKeyDefine.KeyTypeEnum.HASH,
Object.class, RedisKeyDefine.TimeoutTypeEnum.FIXED);
Long userId = 10L;
Integer userType = 1;
// 调用
String key = define.formatKey(userId, userType);
// 断言
assertEquals("user:10:1:30", key);
}
}

View File

@ -1,7 +1,5 @@
package cn.iocoder.yudao.framework.captcha.config; package cn.iocoder.yudao.framework.captcha.config;
import cn.hutool.core.util.ClassUtil;
import cn.iocoder.yudao.framework.captcha.core.enums.CaptchaRedisKeyConstants;
import cn.iocoder.yudao.framework.captcha.core.service.RedisCaptchaServiceImpl; import cn.iocoder.yudao.framework.captcha.core.service.RedisCaptchaServiceImpl;
import com.xingyuv.captcha.properties.AjCaptchaProperties; import com.xingyuv.captcha.properties.AjCaptchaProperties;
import com.xingyuv.captcha.service.CaptchaCacheService; import com.xingyuv.captcha.service.CaptchaCacheService;
@ -15,12 +13,6 @@ import javax.annotation.Resource;
@AutoConfiguration @AutoConfiguration
public class YudaoCaptchaConfiguration { public class YudaoCaptchaConfiguration {
static {
// 手动加载 Lock4jRedisKeyConstants 因为它不会被使用到
// 如果不加载会导致 Redis 监控看到它的 Redis Key 枚举
ClassUtil.loadClass(CaptchaRedisKeyConstants.class.getName());
}
@Resource @Resource
private StringRedisTemplate stringRedisTemplate; private StringRedisTemplate stringRedisTemplate;

View File

@ -1,12 +1,5 @@
package cn.iocoder.yudao.framework.captcha.core.enums; package cn.iocoder.yudao.framework.captcha.core.enums;
import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine;
import com.xingyuv.captcha.model.vo.PointVO;
import java.time.Duration;
import static cn.iocoder.yudao.framework.redis.core.RedisKeyDefine.KeyTypeEnum.STRING;
/** /**
* 验证码 Redis Key 枚举类 * 验证码 Redis Key 枚举类
* *
@ -14,12 +7,22 @@ import static cn.iocoder.yudao.framework.redis.core.RedisKeyDefine.KeyTypeEnum.S
*/ */
public interface CaptchaRedisKeyConstants { public interface CaptchaRedisKeyConstants {
RedisKeyDefine AJ_CAPTCHA_REQ_LIMIT = new RedisKeyDefine("验证码的请求限流", /**
"AJ.CAPTCHA.REQ.LIMIT-%s-%s", * 验证码的请求限流
STRING, Integer.class, Duration.ofSeconds(60)); // 例如说验证失败 5 get 接口锁定 *
* KEY 格式AJ.CAPTCHA.REQ.LIMIT-%s-%s
* VALUE 数据类型String // 例如说验证失败 5 get 接口锁定
* 过期时间60
*/
String AJ_CAPTCHA_REQ_LIMIT = "AJ.CAPTCHA.REQ.LIMIT-%s-%s";
RedisKeyDefine AJ_CAPTCHA_RUNNING = new RedisKeyDefine("验证码的坐标", /**
"RUNNING:CAPTCHA:%s", // AbstractCaptchaService.REDIS_CAPTCHA_KEY * 验证码的坐标
STRING, PointVO.class, Duration.ofSeconds(120)); // {"secretKey":"PP1w2Frr2KEejD2m","x":162,"y":5} *
* KEY 格式RUNNING:CAPTCHA:%s // AbstractCaptchaService.REDIS_CAPTCHA_KEY
* VALUE 数据类型String // PointVO.class {"secretKey":"PP1w2Frr2KEejD2m","x":162,"y":5}
* 过期时间120
*/
String AJ_CAPTCHA_RUNNING = "RUNNING:CAPTCHA:%s";
} }

View File

@ -106,6 +106,7 @@ public interface BaseMapperX<T> extends BaseMapper<T> {
default void updateBatch(Collection<T> entities) { default void updateBatch(Collection<T> entities) {
Db.updateBatchById(entities); Db.updateBatchById(entities);
} }
default void updateBatch(Collection<T> entities, int size) { default void updateBatch(Collection<T> entities, int size) {
Db.updateBatchById(entities, size); Db.updateBatchById(entities, size);
} }

View File

@ -1,13 +1,10 @@
package cn.iocoder.yudao.framework.idempotent.core.redis; package cn.iocoder.yudao.framework.idempotent.core.redis;
import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import static cn.iocoder.yudao.framework.redis.core.RedisKeyDefine.KeyTypeEnum.STRING;
/** /**
* 幂等 Redis DAO * 幂等 Redis DAO
* *
@ -16,9 +13,14 @@ import static cn.iocoder.yudao.framework.redis.core.RedisKeyDefine.KeyTypeEnum.S
@AllArgsConstructor @AllArgsConstructor
public class IdempotentRedisDAO { public class IdempotentRedisDAO {
private static final RedisKeyDefine IDEMPOTENT = new RedisKeyDefine("幂等操作", /**
"idempotent:%s", // 参数为 uuid * 幂等操作
STRING, String.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC); *
* KEY 格式idempotent:%s // 参数为 uuid
* VALUE 格式String
* 过期时间不固定
*/
private static final String IDEMPOTENT = "idempotent:%s";
private final StringRedisTemplate redisTemplate; private final StringRedisTemplate redisTemplate;
@ -28,7 +30,7 @@ public class IdempotentRedisDAO {
} }
private static String formatKey(String key) { private static String formatKey(String key) {
return String.format(IDEMPOTENT.getKeyTemplate(), key); return String.format(IDEMPOTENT, key);
} }
} }

View File

@ -1,21 +1,13 @@
package cn.iocoder.yudao.framework.lock4j.config; package cn.iocoder.yudao.framework.lock4j.config;
import cn.hutool.core.util.ClassUtil;
import com.baomidou.lock.spring.boot.autoconfigure.LockAutoConfiguration;
import cn.iocoder.yudao.framework.lock4j.core.DefaultLockFailureStrategy; import cn.iocoder.yudao.framework.lock4j.core.DefaultLockFailureStrategy;
import cn.iocoder.yudao.framework.lock4j.core.Lock4jRedisKeyConstants; import com.baomidou.lock.spring.boot.autoconfigure.LockAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@AutoConfiguration(before = LockAutoConfiguration.class) @AutoConfiguration(before = LockAutoConfiguration.class)
public class YudaoLock4jConfiguration { public class YudaoLock4jConfiguration {
static {
// 手动加载 Lock4jRedisKeyConstants 因为它不会被使用到
// 如果不加载会导致 Redis 监控看到它的 Redis Key 枚举
ClassUtil.loadClass(Lock4jRedisKeyConstants.class.getName());
}
@Bean @Bean
public DefaultLockFailureStrategy lockFailureStrategy() { public DefaultLockFailureStrategy lockFailureStrategy() {
return new DefaultLockFailureStrategy(); return new DefaultLockFailureStrategy();

View File

@ -1,10 +1,5 @@
package cn.iocoder.yudao.framework.lock4j.core; package cn.iocoder.yudao.framework.lock4j.core;
import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine;
import org.redisson.api.RLock;
import static cn.iocoder.yudao.framework.redis.core.RedisKeyDefine.KeyTypeEnum.HASH;
/** /**
* Lock4j Redis Key 枚举类 * Lock4j Redis Key 枚举类
* *
@ -12,8 +7,13 @@ import static cn.iocoder.yudao.framework.redis.core.RedisKeyDefine.KeyTypeEnum.H
*/ */
public interface Lock4jRedisKeyConstants { public interface Lock4jRedisKeyConstants {
RedisKeyDefine LOCK4J = new RedisKeyDefine("分布式锁", /**
"lock4j:%s", // 参数来自 DefaultLockKeyBuilder * 分布式锁
HASH, RLock.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC); // Redisson Lock 使用 Hash 数据结构 *
* KEY 格式lock4j:%s // 参数来自 DefaultLockKeyBuilder
* VALUE 数据格式HASH // RLock.classRedisson Lock 使用 Hash 数据结构
* 过期时间不固定
*/
String LOCK4J = "lock4j:%s";
} }

View File

@ -1,113 +0,0 @@
package cn.iocoder.yudao.framework.redis.core;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import java.time.Duration;
/**
* Redis Key 定义类
*
* @author 芋道源码
*/
@Data
public class RedisKeyDefine {
@Getter
@AllArgsConstructor
public enum KeyTypeEnum {
STRING("String"),
LIST("List"),
HASH("Hash"),
SET("Set"),
ZSET("Sorted Set"),
STREAM("Stream"),
PUBSUB("Pub/Sub");
/**
* 类型
*/
@JsonValue
private final String type;
}
@Getter
@AllArgsConstructor
public enum TimeoutTypeEnum {
FOREVER(1), // 永不超时
DYNAMIC(2), // 动态超时
FIXED(3); // 固定超时
/**
* 类型
*/
@JsonValue
private final Integer type;
}
/**
* Key 模板
*/
private final String keyTemplate;
/**
* Key 类型的枚举
*/
private final KeyTypeEnum keyType;
/**
* Value 类型
*
* 如果是使用分布式锁设置为 {@link java.util.concurrent.locks.Lock} 类型
*/
private final Class<?> valueType;
/**
* 超时类型
*/
private final TimeoutTypeEnum timeoutType;
/**
* 过期时间
*/
private final Duration timeout;
/**
* 备注
*/
private final String memo;
private RedisKeyDefine(String memo, String keyTemplate, KeyTypeEnum keyType, Class<?> valueType,
TimeoutTypeEnum timeoutType, Duration timeout) {
this.memo = memo;
this.keyTemplate = keyTemplate;
this.keyType = keyType;
this.valueType = valueType;
this.timeout = timeout;
this.timeoutType = timeoutType;
// 添加注册表
RedisKeyRegistry.add(this);
}
public RedisKeyDefine(String memo, String keyTemplate, KeyTypeEnum keyType, Class<?> valueType, Duration timeout) {
this(memo, keyTemplate, keyType, valueType, TimeoutTypeEnum.FIXED, timeout);
}
public RedisKeyDefine(String memo, String keyTemplate, KeyTypeEnum keyType, Class<?> valueType, TimeoutTypeEnum timeoutType) {
this(memo, keyTemplate, keyType, valueType, timeoutType, Duration.ZERO);
}
/**
* 格式化 Key
*
* 注意内部采用 {@link String#format(String, Object...)} 实现
*
* @param args 格式化的参数
* @return Key
*/
public String formatKey(Object... args) {
return String.format(keyTemplate, args);
}
}

View File

@ -1,28 +0,0 @@
package cn.iocoder.yudao.framework.redis.core;
import java.util.ArrayList;
import java.util.List;
/**
* {@link RedisKeyDefine} 注册表
*/
public class RedisKeyRegistry {
/**
* Redis RedisKeyDefine 数组
*/
private static final List<RedisKeyDefine> DEFINES = new ArrayList<>();
public static void add(RedisKeyDefine define) {
DEFINES.add(define);
}
public static List<RedisKeyDefine> list() {
return DEFINES;
}
public static int size() {
return DEFINES.size();
}
}

View File

@ -2,8 +2,3 @@
GET {{baseUrl}}/infra/redis/get-monitor-info GET {{baseUrl}}/infra/redis/get-monitor-info
Authorization: Bearer {{token}} Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}} tenant-id: {{adminTenentId}}
### 请求 /infra/redis/get-key-list 接口 => 成功
GET {{baseUrl}}/infra/redis/get-key-list
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}

View File

@ -1,27 +1,20 @@
package cn.iocoder.yudao.module.infra.controller.admin.redis; package cn.iocoder.yudao.module.infra.controller.admin.redis;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine;
import cn.iocoder.yudao.framework.redis.core.RedisKeyRegistry;
import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisKeyDefineRespVO;
import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisKeyValueRespVO;
import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisMonitorRespVO; import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisMonitorRespVO;
import cn.iocoder.yudao.module.infra.convert.redis.RedisConvert; import cn.iocoder.yudao.module.infra.convert.redis.RedisConvert;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.data.redis.connection.RedisServerCommands; import org.springframework.data.redis.connection.RedisServerCommands;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.*; import java.util.Properties;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@ -47,66 +40,4 @@ public class RedisController {
return success(RedisConvert.INSTANCE.build(info, dbSize, commandStats)); return success(RedisConvert.INSTANCE.build(info, dbSize, commandStats));
} }
@GetMapping("/get-key-define-list")
@Operation(summary = "获得 Redis Key 模板列表")
@PreAuthorize("@ss.hasPermission('infra:redis:get-key-list')")
public CommonResult<List<RedisKeyDefineRespVO>> getKeyDefineList() {
List<RedisKeyDefine> keyDefines = RedisKeyRegistry.list();
return success(RedisConvert.INSTANCE.convertList(keyDefines));
}
@GetMapping("/get-key-list")
@Operation(summary = "获得 Redis keys 键名列表")
@Parameter(name = "keyTemplate", description = "Redis Key 定义", example = "true")
@PreAuthorize("@ss.hasPermission('infra:redis:get-key-list')")
public CommonResult<Set<String>> getKeyDefineList(@RequestParam("keyTemplate") String keyTemplate) {
return success(getKeyDefineList0(keyTemplate));
}
private Set<String> getKeyDefineList0(String keyTemplate) {
// key 格式化
String key = StrUtil.replace(keyTemplate, "%[s|c|b|d|x|o|f|a|e|g]", parameter -> "*");
// scan 扫描 key
Set<String> keys = new LinkedHashSet<>();
stringRedisTemplate.execute((RedisCallback<Set<String>>) connection -> {
try (Cursor<byte[]> cursor = connection.scan(ScanOptions.scanOptions().match(key).count(100).build())) {
cursor.forEachRemaining(value -> keys.add(StrUtil.utf8Str(value)));
} catch (Exception e) {
throw new RuntimeException(e);
}
return keys;
});
return keys;
}
@GetMapping("/get-key-value")
@Operation(summary = "获得 Redis key 内容")
@Parameter(name = "key", description = "Redis Key", example = "oauth2_access_token:233")
@PreAuthorize("@ss.hasPermission('infra:redis:get-key-list')")
public CommonResult<RedisKeyValueRespVO> getKeyValue(@RequestParam("key") String key) {
String value = stringRedisTemplate.opsForValue().get(key);
return success(new RedisKeyValueRespVO(key, value));
}
@DeleteMapping("/delete-key")
@Operation(summary = "删除 Redis Key")
@Parameter(name = "key", description = "Redis Key", example = "oauth2_access_token:233")
@PreAuthorize("@ss.hasPermission('infra:redis:get-key-list')")
public CommonResult<Boolean> deleteKey(@RequestParam("key") String key) {
stringRedisTemplate.delete(key);
return success(Boolean.TRUE);
}
@DeleteMapping("/delete-keys")
@Operation(summary = "删除 Redis Key 根据模板")
@Parameter(name = "keyTemplate", description = "Redis Key 定义", example = "true")
@PreAuthorize("@ss.hasPermission('infra:redis:get-key-list')")
public CommonResult<Boolean> deleteKeys(@RequestParam("keyTemplate") String keyTemplate) {
Set<String> keys = getKeyDefineList0(keyTemplate);
if (CollUtil.isNotEmpty(keys)) {
stringRedisTemplate.delete(keys);
}
return success(Boolean.TRUE);
}
} }

View File

@ -1,35 +0,0 @@
package cn.iocoder.yudao.module.infra.controller.admin.redis.vo;
import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import java.time.Duration;
@Schema(description = "管理后台 - Redis Key 信息 Response VO")
@Data
@Builder
@AllArgsConstructor
public class RedisKeyDefineRespVO {
@Schema(description = "Key 模板", requiredMode = Schema.RequiredMode.REQUIRED, example = "login_user:%s")
private String keyTemplate;
@Schema(description = "Key 类型的枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "String")
private RedisKeyDefine.KeyTypeEnum keyType;
@Schema(description = "Value 类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "java.lang.String")
private Class<?> valueType;
@Schema(description = "超时类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private RedisKeyDefine.TimeoutTypeEnum timeoutType;
@Schema(description = "过期时间,单位:毫秒", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Duration timeout;
@Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "啦啦啦啦~")
private String memo;
}

View File

@ -1,18 +0,0 @@
package cn.iocoder.yudao.module.infra.controller.admin.redis.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
@Schema(description = "管理后台 - 单个 Redis Key Value Response VO")
@Data
@AllArgsConstructor
public class RedisKeyValueRespVO {
@Schema(description = "c5f6990767804a928f4bb96ca249febf", requiredMode = Schema.RequiredMode.REQUIRED, example = "String")
private String key;
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, example = "String")
private String value;
}

View File

@ -1,14 +1,11 @@
package cn.iocoder.yudao.module.infra.convert.redis; package cn.iocoder.yudao.module.infra.convert.redis;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine;
import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisKeyDefineRespVO;
import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisMonitorRespVO; import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisMonitorRespVO;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
import java.util.Properties; import java.util.Properties;
@Mapper @Mapper
@ -29,6 +26,4 @@ public interface RedisConvert {
return respVO; return respVO;
} }
List<RedisKeyDefineRespVO> convertList(List<RedisKeyDefine> list);
} }

View File

@ -1,8 +1,5 @@
package cn.iocoder.yudao.module.pay.dal.redis; package cn.iocoder.yudao.module.pay.dal.redis;
import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine;
import org.redisson.api.RLock;
/** /**
* 支付 Redis Key 枚举类 * 支付 Redis Key 枚举类
* *
@ -10,9 +7,14 @@ import org.redisson.api.RLock;
*/ */
public interface RedisKeyConstants { public interface RedisKeyConstants {
RedisKeyDefine PAY_NOTIFY_LOCK = new RedisKeyDefine("通知任务的分布式锁", /**
"pay_notify:lock:%d", // 参数来自 DefaultLockKeyBuilder * 通知任务的分布式锁
RedisKeyDefine.KeyTypeEnum.HASH, RLock.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC); // Redisson Lock 使用 Hash 数据结构 *
* KEY 格式pay_notify:lock:%d // 参数来自 DefaultLockKeyBuilder
* VALUE 数据格式HASH // RLock.classRedisson Lock 使用 Hash 数据结构
* 过期时间不固定
*/
String PAY_NOTIFY_LOCK = "pay_notify:lock:%d";
/** /**
* 支付序号的缓存 * 支付序号的缓存

View File

@ -33,7 +33,7 @@ public class PayNotifyLockRedisDAO {
} }
private static String formatKey(Long id) { private static String formatKey(Long id) {
return String.format(PAY_NOTIFY_LOCK.getKeyTemplate(), id); return String.format(PAY_NOTIFY_LOCK, id);
} }
} }

View File

@ -2,6 +2,7 @@
POST {{baseUrl}}/system/auth/login POST {{baseUrl}}/system/auth/login
Content-Type: application/json Content-Type: application/json
tenant-id: {{adminTenentId}} tenant-id: {{adminTenentId}}
tag: Yunai.local
{ {
"username": "admin", "username": "admin",