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'