You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Redis 1主2从+3个Sentinel节点架构配置相关技术咨询

Answers to Your Redis Master-Slave & Sentinel Deployment Questions

Hey there! I've worked on several Redis setups with Sentinel and Spring Boot, so let's walk through your questions clearly:

1. Difference between replicaof and slaveof configuration directives

This is purely a naming change introduced in Redis 5.0 to make terminology more accurate (since "slave" has outdated connotations, and "replica" better describes the node's role).

  • Before Redis 5.0, the directive was slaveof <master-ip> <master-port>
  • Starting from Redis 5.0, replicaof <master-ip> <master-port> is the official replacement
  • Functionally, they are identical—Redis still recognizes slaveof for backward compatibility, but it's strongly recommended to use replicaof in new deployments. So for your 2 secondary nodes, go with replicaof if you're running Redis 5.0+; if you're on an older version, stick with slaveof.

2. Can we switch from asynchronous replication to synchronous replication?

Redis doesn't have a global configuration to permanently enable synchronous replication for all writes, but you can enforce synchronous behavior per-write operation using the WAIT command—this fits your low-write, read-heavy scenario perfectly.

Here's how it works:

  • After executing a write command (like SET, HSET) on the master, run WAIT <number-of-replicas> <timeout-in-ms>
  • Example: WAIT 2 0 tells the master to block until at least 2 online replicas have acknowledged the write, with no timeout (wait indefinitely until replicas catch up)
  • This ensures that any subsequent read from replicas will see the latest write, which is ideal for your use case where you want to offload reads to secondary nodes without consistency issues

Note: This will add latency to your write operations (since the master waits for replicas), but since you have few writes, the tradeoff is worth it for read consistency. There's no way to enable this globally for all writes by default—you'll need to either:

  • Modify your application code to call WAIT after critical writes
  • Use a client-side wrapper or Redis proxy that automatically injects the WAIT command for write operations

3. Configure Spring Boot with Redis Sentinel for read-write separation (write to master, read from any replica)

Since you're using RedisSentinelConfiguration with JedisConnectionFactory, here's a step-by-step approach to set up read-write separation:

Step 1: Configure Sentinel connections

First, set up the base RedisSentinelConfiguration:

@Configuration
public class RedisConfig {

    @Value("${redis.master.name}")
    private String masterName;

    @Value("${redis.sentinel.nodes}")
    private List<String> sentinelNodes;

    // Configure Sentinel connection details
    private RedisSentinelConfiguration sentinelConfig() {
        RedisSentinelConfiguration config = new RedisSentinelConfiguration();
        config.master(masterName);
        sentinelNodes.forEach(node -> {
            String[] parts = node.split(":");
            config.sentinel(parts[0], Integer.parseInt(parts[1]));
        });
        return config;
    }
}

Step 2: Create two JedisConnectionFactory beans (one for write, one for read)

We'll create a primary factory for writes (points to master) and a secondary factory that prioritizes replicas for reads:

// Primary factory for write operations (uses master node)
@Bean
@Primary
public JedisConnectionFactory masterJedisConnectionFactory() {
    return new JedisConnectionFactory(sentinelConfig());
}

// Factory for read operations (prefers replica nodes)
@Bean(name = "replicaJedisConnectionFactory")
public JedisConnectionFactory replicaJedisConnectionFactory() {
    RedisSentinelConfiguration config = sentinelConfig();
    // Configure to read from replicas first; fall back to master if no replicas are available
    config.setReadFrom(ReadFrom.REPLICA_PREFERRED);
    return new JedisConnectionFactory(config);
}

Step 3: Create two RedisTemplate beans (one for write, one for read)

Bind each factory to a dedicated RedisTemplate so you can inject them where needed:

// Primary RedisTemplate for write operations
@Bean
@Primary
public RedisTemplate<String, Object> masterRedisTemplate() {
    RedisTemplate<String, Object> template = new RedisTemplate<>();
    template.setConnectionFactory(masterJedisConnectionFactory());
    // Configure serializers (adjust based on your data types)
    template.setKeySerializer(new StringRedisSerializer());
    template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
    return template;
}

// RedisTemplate for read operations
@Bean(name = "replicaRedisTemplate")
public RedisTemplate<String, Object> replicaRedisTemplate() {
    RedisTemplate<String, Object> template = new RedisTemplate<>();
    template.setConnectionFactory(replicaJedisConnectionFactory());
    template.setKeySerializer(new StringRedisSerializer());
    template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
    return template;
}

Step 4: Use the templates in your service layer

Inject the appropriate template based on the operation:

@Service
public class RedisDataService {

    @Autowired
    @Qualifier("masterRedisTemplate")
    private RedisTemplate<String, Object> masterRedisTemplate;

    @Autowired
    @Qualifier("replicaRedisTemplate")
    private RedisTemplate<String, Object> replicaRedisTemplate;

    // Write operation - uses master template
    public void saveData(String key, Object value) {
        masterRedisTemplate.opsForValue().set(key, value);
        // Optional: Add WAIT command here if you need synchronous replication for this write
        masterRedisTemplate.execute((RedisCallback<Void>) connection -> {
            connection.wait(2, 0); // Wait for 2 replicas to acknowledge
            return null;
        });
    }

    // Read operation - uses replica template
    public Object getData(String key) {
        return replicaRedisTemplate.opsForValue().get(key);
    }
}

Alternatively, if you want a more transparent approach (without injecting two templates), you can use AOP to route read/write methods to the appropriate template, but the above method is straightforward and easy to debug.


内容的提问来源于stack exchange,提问作者CrazyCoder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.01 01:12:29