redis叢集主從之讀寫分離
阿新 • • 發佈:2018-11-27
redis叢集主從之讀寫分離
1、叢集部署 這裡就不詳細贅述如何部署主從叢集了,一般都是使用slaveOf配置來進行初始化配置。
2、與springboot整合實現讀寫分離 通過註解實現呼叫層讀寫分離,然後根據取模運算來確定訪問哪個讀庫
- 在springcloud配置中心增加redis配置:
配置讀寫節點
spring: redis: database: 0 pool: max-active: 8 max-idle: 9 max-wait: -1 min-idle: 0 redis-master: host: 192.168.1.1 prot: 6379 password: testOnBorrow: false redis-slave1: host: 192.168.1.2 prot: 6379 password: testOnBorrow: false redis-slave2: host: 192.168.1.3 prot: 6379 password: testOnBorrow: false
- 增加自動配置類
如下:
@Configuration public class RedisConfiguration { @Value("${spring.redis.pool.max-idle}") private int maxIdle; @Value("${spring.redis.pool.max-active}") private int maxTotal; @Value("${spring.redis.database}") private int index; @Value("${spring.redis.pool.max-wait}") private long maxWaitMillis; @Bean(name = "redisMasterTemplate") public StringRedisTemplate redisMasterTemplate(@Value("${spring.redis-master.host}") String hostName, @Value("${spring.redis-master.port}") int port, @Value("${spring.redis-master.password}") String password, @Value("${spring.redis-master.testOnBorrow}") boolean testOnBorrow) { StringRedisTemplate temple = new StringRedisTemplate(); temple.setConnectionFactory( connectionFactory(hostName, port, password, maxIdle, maxTotal, index, maxWaitMillis, testOnBorrow)); return temple; } @Bean(name = "redisSlave1Template") public StringRedisTemplate redisSlave1Template(@Value("${spring.redis-slave1.host}") String hostName, @Value("${spring.redis-slave1.port}") int port, @Value("${spring.redis-slave1.password}") String password, @Value("${spring.redis-slave1.testOnBorrow}") boolean testOnBorrow) { StringRedisTemplate temple = new StringRedisTemplate(); temple.setConnectionFactory( connectionFactory(hostName, port, password, maxIdle, maxTotal, index, maxWaitMillis, testOnBorrow)); return temple; } @Bean(name = "redisSlave1Template") public List<StringRedisTemplate> redisSlaveTemplate() { List<StringRedisTemplate> list = new ArrayList<StringRedisTemplate>(); list.add(redisSlave1Template()); list.add(redisSlave2Template()); return list; } @Bean(name = "redisSlave2Template") public StringRedisTemplate redisSlave1Template(@Value("${spring.redis-slave2.host}") String hostName, @Value("${spring.redis-slave2.port}") int port, @Value("${spring.redis-slave2.password}") String password, @Value("${spring.redis-slave2.testOnBorrow}") boolean testOnBorrow) { StringRedisTemplate temple = new StringRedisTemplate(); temple.setConnectionFactory( connectionFactory(hostName, port, password, maxIdle, maxTotal, index, maxWaitMillis, testOnBorrow)); return temple; } public RedisConnectionFactory connectionFactory(String hostName, int port, String password, int maxIdle, int maxTotal, int index, long maxWaitMillis, boolean testOnBorrow) { JedisConnectionFactory jedis = new JedisConnectionFactory(); jedis.setHostName(hostName); jedis.setPort(port); if (StringUtils.isNotEmpty(password)) { jedis.setPassword(password); } if (index != 0) { jedis.setDatabase(index); } jedis.setPoolConfig(poolCofig(maxIdle, maxTotal, maxWaitMillis, testOnBorrow)); // 初始化連線pool jedis.afterPropertiesSet(); RedisConnectionFactory factory = jedis; return factory; } public JedisPoolConfig poolCofig(int maxIdle, int maxTotal, long maxWaitMillis, boolean testOnBorrow) { JedisPoolConfig poolCofig = new JedisPoolConfig(); poolCofig.setMaxIdle(maxIdle); poolCofig.setMaxTotal(maxTotal); poolCofig.setMaxWaitMillis(maxWaitMillis); poolCofig.setTestOnBorrow(testOnBorrow); return poolCofig; } }
封裝呼叫介面
@Component public class StringRedisTemplateProxy { @Autowired private StringRedisTemplate redisMasterTemplate; @Autowired private List<StringRedisTemplate> redisSlaveList; private int index=0; public void setValue(String key,String value) { redisMasterTemplate.opsForValue().set(key, value); } public String getValue(String key) { index++; return redisSlaveList.get(index).opsForValue().get(key); } }
這裡缺點就是無法做到故障轉移,這裡就需要用到虛擬ip和指令碼定時監控。 1、使用一個虛擬ip指向redis master 2、如果從節點故障,可以採用重試機制來進行一次呼叫讀節點,如果是主節點故障,則需要通過指令碼自動將一個從節點切換成主節點,並將虛擬IP繫結在該節點上。