From cd617d6c46216d1bc1585d171a596cd6c7a3ac87 Mon Sep 17 00:00:00 2001 From: ay_g <3245669550@qq.com> Date: Sat, 9 May 2026 11:25:01 +0800 Subject: [PATCH] =?UTF-8?q?=E5=89=8D=E7=BC=80key=E5=BA=8F=E5=88=97?= =?UTF-8?q?=E5=8C=96=E5=99=A8=E4=B8=8D=E7=94=9F=E6=95=88=E9=97=AE=E9=A2=98?= =?UTF-8?q?=EF=BC=8C=E4=BB=A5=E5=8F=8A=E5=88=86=E5=B8=83=E5=BC=8Fid?= =?UTF-8?q?=E6=B2=A1=E5=8A=A0=E7=BB=9F=E4=B8=80=E5=89=8D=E7=BC=80=E9=97=AE?= =?UTF-8?q?=E9=A2=98=EF=BC=8C=E6=96=B0=E5=A2=9E=E8=87=AA=E5=8A=A8=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E7=B1=BB=EF=BC=8C=E6=B3=A8=E5=86=8C=E5=BA=8F=E5=88=97?= =?UTF-8?q?=E5=8C=96=E5=99=A8=EF=BC=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/cache/RedisKeySerializer.java | 17 +++- .../RedisKeyPrefixAutoConfiguration.java | 82 +++++++++++++++++++ .../distributedid/SnowflakeIdInitializer.java | 5 +- .../src/main/resources/lua/snowflake_init.lua | 2 +- 4 files changed, 100 insertions(+), 6 deletions(-) create mode 100644 framework/src/main/java/com/nageoffer/ai/ragent/framework/config/RedisKeyPrefixAutoConfiguration.java diff --git a/framework/src/main/java/com/nageoffer/ai/ragent/framework/cache/RedisKeySerializer.java b/framework/src/main/java/com/nageoffer/ai/ragent/framework/cache/RedisKeySerializer.java index 910f7d13..590d1b45 100644 --- a/framework/src/main/java/com/nageoffer/ai/ragent/framework/cache/RedisKeySerializer.java +++ b/framework/src/main/java/com/nageoffer/ai/ragent/framework/cache/RedisKeySerializer.java @@ -39,12 +39,23 @@ public class RedisKeySerializer implements RedisSerializer { @Override public byte[] serialize(String key) throws SerializationException { - String builderKey = keyPrefix + key; - return builderKey.getBytes(); + if (key == null) { + return null; + } + String actualKey = hasPrefix(key) ? key : keyPrefix + key; + return actualKey.getBytes(StandardCharsets.UTF_8); } @Override public String deserialize(byte[] bytes) throws SerializationException { - return new String(bytes, StandardCharsets.UTF_8); + if (bytes == null) { + return null; + } + String actualKey = new String(bytes, StandardCharsets.UTF_8); + return hasPrefix(actualKey) ? actualKey.substring(keyPrefix.length()) : actualKey; + } + + private boolean hasPrefix(String key) { + return keyPrefix != null && !keyPrefix.isEmpty() && key.startsWith(keyPrefix); } } diff --git a/framework/src/main/java/com/nageoffer/ai/ragent/framework/config/RedisKeyPrefixAutoConfiguration.java b/framework/src/main/java/com/nageoffer/ai/ragent/framework/config/RedisKeyPrefixAutoConfiguration.java new file mode 100644 index 00000000..2d84914f --- /dev/null +++ b/framework/src/main/java/com/nageoffer/ai/ragent/framework/config/RedisKeyPrefixAutoConfiguration.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.nageoffer.ai.ragent.framework.config; + +import com.nageoffer.ai.ragent.framework.cache.RedisKeySerializer; +import org.jspecify.annotations.NonNull; +import org.redisson.config.NameMapper; +import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.core.StringRedisTemplate; + +/** + * Redis key prefix configuration. + */ +@Configuration +@ConditionalOnProperty(name = "framework.cache.redis.prefix") +public class RedisKeyPrefixAutoConfiguration { + + @Bean + public BeanPostProcessor stringRedisTemplateKeyPrefixPostProcessor(RedisKeySerializer redisKeySerializer) { + return new BeanPostProcessor() { + @Override + public Object postProcessBeforeInitialization(@NonNull Object bean, @NonNull String beanName) throws BeansException { + if (bean instanceof StringRedisTemplate template) { + template.setKeySerializer(redisKeySerializer); + template.setHashKeySerializer(redisKeySerializer); + } + return bean; + } + }; + } + + @Bean + public RedissonAutoConfigurationCustomizer redissonKeyPrefixCustomizer( + @Value("${framework.cache.redis.prefix}") String keyPrefix) { + return config -> config.setNameMapper(new PrefixNameMapper(keyPrefix, config.getNameMapper())); + } + + private record PrefixNameMapper(String keyPrefix, NameMapper delegate) implements NameMapper { + + @Override + public String map(String name) { + String mappedName = delegate.map(name); + if (mappedName == null || hasPrefix(mappedName)) { + return mappedName; + } + return keyPrefix + mappedName; + } + + @Override + public String unmap(String name) { + if (name == null || !hasPrefix(name)) { + return delegate.unmap(name); + } + return delegate.unmap(name.substring(keyPrefix.length())); + } + + private boolean hasPrefix(String name) { + return keyPrefix != null && !keyPrefix.isEmpty() && name.startsWith(keyPrefix); + } + } +} diff --git a/framework/src/main/java/com/nageoffer/ai/ragent/framework/distributedid/SnowflakeIdInitializer.java b/framework/src/main/java/com/nageoffer/ai/ragent/framework/distributedid/SnowflakeIdInitializer.java index 9b5a432e..709ea895 100644 --- a/framework/src/main/java/com/nageoffer/ai/ragent/framework/distributedid/SnowflakeIdInitializer.java +++ b/framework/src/main/java/com/nageoffer/ai/ragent/framework/distributedid/SnowflakeIdInitializer.java @@ -29,7 +29,6 @@ import org.springframework.scripting.support.ResourceScriptSource; import org.springframework.stereotype.Component; -import java.util.Collections; import java.util.List; /** @@ -41,6 +40,8 @@ @RequiredArgsConstructor public class SnowflakeIdInitializer { + private static final String SNOWFLAKE_WORK_ID_KEY = "snowflake_work_id_key"; + private final StringRedisTemplate stringRedisTemplate; @SuppressWarnings({"rawtypes", "unchecked"}) @@ -53,7 +54,7 @@ public void init() { try { // 执行 Lua 脚本获取 workerId 和 datacenterId - List result = stringRedisTemplate.execute(script, Collections.emptyList()); + List result = stringRedisTemplate.execute(script, List.of(SNOWFLAKE_WORK_ID_KEY)); if (CollUtil.isEmpty(result) || result.size() != 2) { throw new RuntimeException("从Redis获取WorkerId和DataCenterId失败"); diff --git a/framework/src/main/resources/lua/snowflake_init.lua b/framework/src/main/resources/lua/snowflake_init.lua index 1f8694b9..07a03f5a 100644 --- a/framework/src/main/resources/lua/snowflake_init.lua +++ b/framework/src/main/resources/lua/snowflake_init.lua @@ -1,4 +1,4 @@ -local hashKey = 'snowflake_work_id_key' +local hashKey = KEYS[1] local dataCenterIdKey = 'dataCenterId' local workIdKey = 'workId'