Bläddra i källkod

仅当配置了 spring.redis.sentinel.master 时生效;未配 Sentinel 时仍走自动配置。

dujian 1 månad sedan
förälder
incheckning
191be03ebe
1 ändrade filer med 114 tillägg och 114 borttagningar
  1. 114 114
      alien-store/src/main/java/shop/alien/store/config/RedisLettuceConfig.java

+ 114 - 114
alien-store/src/main/java/shop/alien/store/config/RedisLettuceConfig.java

@@ -1,114 +1,114 @@
-//package shop.alien.store.config;
-//
-//import io.lettuce.core.RedisURI;
-//import io.lettuce.core.sentinel.api.sync.RedisSentinelCommands;
-//import lombok.extern.slf4j.Slf4j;
-//import org.springframework.boot.autoconfigure.AutoConfigureBefore;
-//import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
-//import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
-//import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-//import org.springframework.beans.factory.annotation.Value;
-//import org.springframework.context.annotation.Bean;
-//import org.springframework.context.annotation.Configuration;
-//import org.springframework.context.annotation.Primary;
-//import org.springframework.data.redis.connection.RedisPassword;
-//import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
-//import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
-//import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
-//import org.springframework.util.StringUtils;
-//
-//import java.util.List;
-//import java.util.Map;
-//
-///**
-// * 使用 Sentinel 时:启动阶段向 Sentinel 查询当前 Master 地址,并只建立到该 Master 的独立连接(单节点)。
-// * 不建 MasterReplica 拓扑,从根源上避免请求被路由到只读副本导致 READONLY。
-// * 仅当配置了 spring.redis.sentinel.master 时生效;未配 Sentinel 时仍走自动配置。
-// */
-//@Slf4j
-//@Configuration
-//@AutoConfigureBefore(RedisAutoConfiguration.class)
-//public class RedisLettuceConfig {
-//
-//    @Bean
-//    @Primary
-//    @ConditionalOnProperty(
-//            prefix = "spring.redis.sentinel",
-//            name = "master",
-//            matchIfMissing = false)
-//    public LettuceConnectionFactory redisConnectionFactory(
-//            RedisProperties properties,
-//            @Value("${spring.redis.master-port:#{null}}") Integer masterPortOverride) {
-//        log.info("RedisLettuceConfig: 使用 Sentinel 解析 Master 并创建仅连 Master 的 Redis 连接(避免 READONLY)");
-//        RedisProperties.Sentinel sentinel = properties.getSentinel();
-//        String masterName = sentinel.getMaster();
-//        String[] firstSentinel = parseFirstSentinelNode(sentinel.getNodes());
-//        if (firstSentinel == null) {
-//            throw new IllegalStateException("spring.redis.sentinel.nodes 未配置或格式错误");
-//        }
-//        String sentinelHost = firstSentinel[0];
-//        int sentinelPort = Integer.parseInt(firstSentinel[1]);
-//
-//        // 向 Sentinel 查询当前 Master 地址
-//        String masterHost;
-//        int masterPort;
-//        io.lettuce.core.RedisClient probeClient = null;
-//        try {
-//            probeClient = io.lettuce.core.RedisClient.create(
-//                    RedisURI.create("redis://" + sentinelHost + ":" + sentinelPort));
-//            try (io.lettuce.core.sentinel.api.StatefulRedisSentinelConnection<String, String> probeConn =
-//                    probeClient.connectSentinel()) {
-//                RedisSentinelCommands<String, String> sync = probeConn.sync();
-//                Map<String, String> master = sync.master(masterName);
-//                if (master == null || !master.containsKey("ip") || !master.containsKey("port")) {
-//                    throw new IllegalStateException("Sentinel 未返回 master 地址: " + masterName);
-//                }
-//                masterHost = master.get("ip");
-//                masterPort = Integer.parseInt(master.get("port"));
-//                // 若配置了 spring.redis.master-port(如宿主机映射 30012),用其覆盖 Sentinel 返回的端口
-//                if (masterPortOverride != null) {
-//                    masterPort = masterPortOverride;
-//                }
-//                log.info("Redis Sentinel 当前 Master: {}:{} (masterName={})", masterHost, masterPort, masterName);
-//            }
-//        } finally {
-//            if (probeClient != null) {
-//                probeClient.shutdown();
-//            }
-//        }
-//
-//        // 仅连接该 Master 单节点,不建 MasterReplica,避免请求打到副本
-//        RedisStandaloneConfiguration standaloneConfig = new RedisStandaloneConfiguration(masterHost, masterPort);
-//        standaloneConfig.setDatabase(properties.getDatabase());
-//        if (StringUtils.hasText(properties.getPassword())) {
-//            standaloneConfig.setPassword(RedisPassword.of(properties.getPassword()));
-//        }
-//
-//        LettuceClientConfiguration.LettuceClientConfigurationBuilder builder = LettuceClientConfiguration.builder();
-//        if (properties.getTimeout() != null) {
-//            builder.commandTimeout(properties.getTimeout());
-//        }
-//        LettuceClientConfiguration clientConfig = builder.build();
-//
-//        LettuceConnectionFactory factory = new LettuceConnectionFactory(standaloneConfig, clientConfig);
-//        return factory;
-//    }
-//
-//    private static String[] parseFirstSentinelNode(List<String> nodes) {
-//        if (nodes == null || nodes.isEmpty()) {
-//            return null;
-//        }
-//        for (String node : nodes) {
-//            for (String one : node.split(",")) {
-//                String hostPort = one.trim();
-//                if (!hostPort.isEmpty()) {
-//                    String[] parts = hostPort.split(":");
-//                    String host = parts[0].trim();
-//                    String port = parts.length > 1 ? parts[1].trim() : "26379";
-//                    return new String[]{host, port};
-//                }
-//            }
-//        }
-//        return null;
-//    }
-//}
+package shop.alien.store.config;
+
+import io.lettuce.core.RedisURI;
+import io.lettuce.core.sentinel.api.sync.RedisSentinelCommands;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.autoconfigure.AutoConfigureBefore;
+import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
+import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.data.redis.connection.RedisPassword;
+import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
+import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
+import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
+import org.springframework.util.StringUtils;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 使用 Sentinel 时:启动阶段向 Sentinel 查询当前 Master 地址,并只建立到该 Master 的独立连接(单节点)。
+ * 不建 MasterReplica 拓扑,从根源上避免请求被路由到只读副本导致 READONLY。
+ * 仅当配置了 spring.redis.sentinel.master 时生效;未配 Sentinel 时仍走自动配置。
+ */
+@Slf4j
+@Configuration
+@AutoConfigureBefore(RedisAutoConfiguration.class)
+public class RedisLettuceConfig {
+
+    @Bean
+    @Primary
+    @ConditionalOnProperty(
+            prefix = "spring.redis.sentinel",
+            name = "master",
+            matchIfMissing = false)
+    public LettuceConnectionFactory redisConnectionFactory(
+            RedisProperties properties,
+            @Value("${spring.redis.master-port:#{null}}") Integer masterPortOverride) {
+        log.info("RedisLettuceConfig: 使用 Sentinel 解析 Master 并创建仅连 Master 的 Redis 连接(避免 READONLY)");
+        RedisProperties.Sentinel sentinel = properties.getSentinel();
+        String masterName = sentinel.getMaster();
+        String[] firstSentinel = parseFirstSentinelNode(sentinel.getNodes());
+        if (firstSentinel == null) {
+            throw new IllegalStateException("spring.redis.sentinel.nodes 未配置或格式错误");
+        }
+        String sentinelHost = firstSentinel[0];
+        int sentinelPort = Integer.parseInt(firstSentinel[1]);
+
+        // 向 Sentinel 查询当前 Master 地址
+        String masterHost;
+        int masterPort;
+        io.lettuce.core.RedisClient probeClient = null;
+        try {
+            probeClient = io.lettuce.core.RedisClient.create(
+                    RedisURI.create("redis://" + sentinelHost + ":" + sentinelPort));
+            try (io.lettuce.core.sentinel.api.StatefulRedisSentinelConnection<String, String> probeConn =
+                    probeClient.connectSentinel()) {
+                RedisSentinelCommands<String, String> sync = probeConn.sync();
+                Map<String, String> master = sync.master(masterName);
+                if (master == null || !master.containsKey("ip") || !master.containsKey("port")) {
+                    throw new IllegalStateException("Sentinel 未返回 master 地址: " + masterName);
+                }
+                masterHost = master.get("ip");
+                masterPort = Integer.parseInt(master.get("port"));
+                // 若配置了 spring.redis.master-port(如宿主机映射 30012),用其覆盖 Sentinel 返回的端口
+                if (masterPortOverride != null) {
+                    masterPort = masterPortOverride;
+                }
+                log.info("Redis Sentinel 当前 Master: {}:{} (masterName={})", masterHost, masterPort, masterName);
+            }
+        } finally {
+            if (probeClient != null) {
+                probeClient.shutdown();
+            }
+        }
+
+        // 仅连接该 Master 单节点,不建 MasterReplica,避免请求打到副本
+        RedisStandaloneConfiguration standaloneConfig = new RedisStandaloneConfiguration(masterHost, masterPort);
+        standaloneConfig.setDatabase(properties.getDatabase());
+        if (StringUtils.hasText(properties.getPassword())) {
+            standaloneConfig.setPassword(RedisPassword.of(properties.getPassword()));
+        }
+
+        LettuceClientConfiguration.LettuceClientConfigurationBuilder builder = LettuceClientConfiguration.builder();
+        if (properties.getTimeout() != null) {
+            builder.commandTimeout(properties.getTimeout());
+        }
+        LettuceClientConfiguration clientConfig = builder.build();
+
+        LettuceConnectionFactory factory = new LettuceConnectionFactory(standaloneConfig, clientConfig);
+        return factory;
+    }
+
+    private static String[] parseFirstSentinelNode(List<String> nodes) {
+        if (nodes == null || nodes.isEmpty()) {
+            return null;
+        }
+        for (String node : nodes) {
+            for (String one : node.split(",")) {
+                String hostPort = one.trim();
+                if (!hostPort.isEmpty()) {
+                    String[] parts = hostPort.split(":");
+                    String host = parts[0].trim();
+                    String port = parts.length > 1 ? parts[1].trim() : "26379";
+                    return new String[]{host, port};
+                }
+            }
+        }
+        return null;
+    }
+}