redis哨兵实现读写分离和高可靠,使用过程中是不是会出现两种问题,一种是会报socket reset异常考虑分析可能是master节点故障,客户端仍然连接旧的master; 一种是报slave写错误,考虑是故障节点重启后,仍然往旧的master中写数据。
单独写了测试类复现分析这个头疼的问题。
架构
Client: spring data redis、 jedis
Redis 3台,1台master,2台slave,三台redis sentinel.
Redis Sentinel 集群看成是一个 ZooKeeper 集群,一般是由 3~5 个节点组成,
负责持续监控主从节点的健康,当主节点挂掉时,自动选择一个最优的从节点切换为主节点。
- 客户端来连接集群时,会首先连接 sentinel,通过 sentinel 来查询主节点的地址,然后再去连接主节点进行数据交互。
- 当主节点发生故障时,客户端会重新向 sentinel 要地址,sentinel 会将最新的主节点地址告诉客户端。如此应用程序将无需重启即可自动完成节点切换。
Redis配置
@Configuration
public class RedisConfiguration {
@Value("${redis.sentinel.master}")
private String master;
@Value("${redis.sentinel.nodes}")
private String nodes;
@Bean
public JedisPoolConfig jedisPoolConfig() {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxIdle(100);
jedisPoolConfig.setMinIdle(8);
jedisPoolConfig.setMaxTotal(500);
jedisPoolConfig.setMaxWaitMillis(3000);
// jedisPoolConfig.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
// jedisPoolConfig.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
// jedisPoolConfig.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
jedisPoolConfig.setTestOnBorrow(true);
jedisPoolConfig.setTestWhileIdle(true);
return jedisPoolConfig;
}
@Bean
public CSBRedisSentinelConfiguration sentinelConfiguration() {
CSBRedisSentinelConfiguration redisSentinelConfiguration = new CSBRedisSentinelConfiguration(master, nodes);
redisSentinelConfiguration.setPassword("");
return redisSentinelConfiguration;
}
@Bean
pub