|
@@ -1,18 +1,53 @@
|
|
|
package shop.alien.store.config;
|
|
package shop.alien.store.config;
|
|
|
|
|
|
|
|
import io.lettuce.core.ReadFrom;
|
|
import io.lettuce.core.ReadFrom;
|
|
|
-import org.springframework.boot.autoconfigure.data.redis.LettuceClientConfigurationBuilderCustomizer;
|
|
|
|
|
|
|
+import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
|
|
|
|
|
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|
|
import org.springframework.context.annotation.Bean;
|
|
import org.springframework.context.annotation.Bean;
|
|
|
import org.springframework.context.annotation.Configuration;
|
|
import org.springframework.context.annotation.Configuration;
|
|
|
|
|
+import org.springframework.data.redis.connection.RedisPassword;
|
|
|
|
|
+import org.springframework.data.redis.connection.RedisSentinelConfiguration;
|
|
|
|
|
+import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
|
|
|
|
|
+import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
|
|
|
|
+import org.springframework.util.StringUtils;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * Lettuce 配置。使用 Sentinel 时强制读写都走 Master,避免写请求被路由到只读副本导致 READONLY。
|
|
|
|
|
|
|
+ * 使用 Sentinel 时显式创建 RedisConnectionFactory,强制 ReadFrom.MASTER,避免写请求打到只读副本导致 READONLY。
|
|
|
|
|
+ * 仅当配置了 spring.redis.sentinel.master 时生效;未配 Sentinel 时仍走自动配置。
|
|
|
*/
|
|
*/
|
|
|
@Configuration
|
|
@Configuration
|
|
|
public class RedisLettuceConfig {
|
|
public class RedisLettuceConfig {
|
|
|
|
|
|
|
|
@Bean
|
|
@Bean
|
|
|
- public LettuceClientConfigurationBuilderCustomizer lettuceClientConfigurationBuilderCustomizer() {
|
|
|
|
|
- return builder -> builder.readFrom(ReadFrom.MASTER);
|
|
|
|
|
|
|
+ @ConditionalOnProperty(prefix = "spring.redis.sentinel", name = "master")
|
|
|
|
|
+ public LettuceConnectionFactory redisConnectionFactory(RedisProperties properties) {
|
|
|
|
|
+ RedisProperties.Sentinel sentinel = properties.getSentinel();
|
|
|
|
|
+ RedisSentinelConfiguration sentinelConfig = new RedisSentinelConfiguration()
|
|
|
|
|
+ .master(sentinel.getMaster());
|
|
|
|
|
+ for (String node : sentinel.getNodes()) {
|
|
|
|
|
+ for (String one : node.split(",")) {
|
|
|
|
|
+ String hostPort = one.trim();
|
|
|
|
|
+ if (!hostPort.isEmpty()) {
|
|
|
|
|
+ String[] parts = hostPort.split(":");
|
|
|
|
|
+ String host = parts[0].trim();
|
|
|
|
|
+ int port = parts.length > 1 ? Integer.parseInt(parts[1].trim()) : 26379;
|
|
|
|
|
+ sentinelConfig.sentinel(host, port);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (StringUtils.hasText(properties.getPassword())) {
|
|
|
|
|
+ sentinelConfig.setPassword(RedisPassword.of(properties.getPassword()));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ LettuceClientConfiguration.LettuceClientConfigurationBuilder builder = LettuceClientConfiguration.builder()
|
|
|
|
|
+ .readFrom(ReadFrom.MASTER);
|
|
|
|
|
+ if (properties.getTimeout() != null) {
|
|
|
|
|
+ builder.commandTimeout(properties.getTimeout());
|
|
|
|
|
+ }
|
|
|
|
|
+ LettuceClientConfiguration clientConfig = builder.build();
|
|
|
|
|
+
|
|
|
|
|
+ LettuceConnectionFactory factory = new LettuceConnectionFactory(sentinelConfig, clientConfig);
|
|
|
|
|
+ factory.setDatabase(properties.getDatabase());
|
|
|
|
|
+ return factory;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|