0032【Redis】简单玩玩从Redis单机扩展到一主二从三哨兵模式

0032【Redis】简单玩玩从Redis单机扩展到一主二从三哨兵模式

二 一主二从三哨兵

端口配置:
主:6371
从1:6372
从2:6373
哨兵1:26371
哨兵2:26372
哨兵3:26373

2.1 一主

2.1.1 配置

port 6371
bind 192.168.0.101
dir /Users/chyzhong/01-worktools/08-redis-6.0.8-cluster/3-data
pidfile /Users/chyzhong/01-worktools/08-redis-6.0.8-cluster/2-pid/redis-6371-master.pid
logfile /Users/chyzhong/01-worktools/08-redis-6.0.8-cluster/5-logs/redis-6371-master.log
appendfilename "appendonly-6371-master.aof"
dbfilename dump-6371-master.rdb
requirepass "gzst2022"
masterauth "gzst2022"

2.1.2 启动

/Users/chyzhong/01-worktools/08-redis-6.0.8/bin/redis-server /Users/chyzhong/01-worktools/08-redis-6.0.8-cluster/1-conf/redis-6371-master.conf

2.2 二从

2.2.1 从1配置

port 6372
bind 192.168.0.101
dir /Users/chyzhong/01-worktools/08-redis-6.0.8-cluster/3-data
pidfile /Users/chyzhong/01-worktools/08-redis-6.0.8-cluster/2-pid/redis-6372-slave.pid
logfile /Users/chyzhong/01-worktools/08-redis-6.0.8-cluster/5-logs/redis-6372-slave.log
appendfilename appendonly-6372-slave.aof
dbfilename dump-6372-slave.rdb
requirepass "gzst2022"
masterauth "gzst2022"

slaveof 192.168.0.101 6371 # IP与主机一致,才可以复制数据,运行后slaveof变为replicaof

2.2.2 从2配置

port 6373
bind 192.168.0.101
dir /Users/chyzhong/01-worktools/08-redis-6.0.8-cluster/3-data
pidfile /Users/chyzhong/01-worktools/08-redis-6.0.8-cluster/2-pid/redis-6373-slave.pid
logfile /Users/chyzhong/01-worktools/08-redis-6.0.8-cluster/5-logs/redis-6373-slave.log
appendfilename appendonly-6373-slave.aof
dbfilename dump-6373-slave.rdb
requirepass "gzst2022"
masterauth "gzst2022"

slaveof 192.168.0.101 6371 # IP与主机一致,才可以复制数据,运行后slaveof变为replicaof

2.2.3 启动

/Users/chyzhong/01-worktools/08-redis-6.0.8/bin/redis-server /Users/chyzhong/01-worktools/08-redis-6.0.8-cluster/1-conf/redis-6372-slave.conf

/Users/chyzhong/01-worktools/08-redis-6.0.8/bin/redis-server /Users/chyzhong/01-worktools/08-redis-6.0.8-cluster/1-conf/redis-6373-slave.conf

2.3 三哨兵

2.3.1 哨兵1配置

port 26371
bind 192.168.0.101
#requirepass "gzst2022" #不要设置密码
sentinel monitor mymaster 192.168.0.101 6371 2
sentinel auth-pass mymaster gzst2022 #放在monitor mymaster参数后面,否则报错:No such master with specified name
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 15000
protected-mode no
daemonize yes # 守护进程
pidfile /Users/chyzhong/01-worktools/08-redis-6.0.8-cluster/2-pid/redis-26371-sentinel.pid
dir /Users/chyzhong/01-worktools/08-redis-6.0.8-cluster/3-data
logfile /Users/chyzhong/01-worktools/08-redis-6.0.8-cluster/5-logs/redis-26371-sentinel.log

2.3.2 哨兵2配置

port 26372
bind 192.168.0.101
#requirepass "gzst2022" #不要设置密码
sentinel monitor mymaster 192.168.0.101 6371 2
sentinel auth-pass mymaster gzst2022 #放在monitor mymaster参数后面,否则报错:No such master with specified name
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 15000
protected-mode no
daemonize yes # 守护进程
pidfile /Users/chyzhong/01-worktools/08-redis-6.0.8-cluster/2-pid/redis-26372-sentinel.pid
dir /Users/chyzhong/01-worktools/08-redis-6.0.8-cluster/3-data
logfile /Users/chyzhong/01-worktools/08-redis-6.0.8-cluster/5-logs/redis-26372-sentinel.log

2.3.3 哨兵3配置

port 26373
bind 192.168.0.101
#requirepass "gzst2022" #不要设置密码
sentinel monitor mymaster 192.168.0.101 6371 2
sentinel auth-pass mymaster gzst2022 #放在monitor mymaster参数后面,否则报错:No such master with specified name
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 15000
protected-mode no
daemonize yes # 守护进程
pidfile /Users/chyzhong/01-worktools/08-redis-6.0.8-cluster/2-pid/redis-26373-sentinel.pid
dir /Users/chyzhong/01-worktools/08-redis-6.0.8-cluster/3-data
logfile /Users/chyzhong/01-worktools/08-redis-6.0.8-cluster/5-logs/redis-26373-sentinel.log

2.3.4 启动

/Users/chyzhong/01-worktools/08-redis-6.0.8/bin/redis-server /Users/chyzhong/01-worktools/08-redis-6.0.8-cluster/1-conf/redis-26371-sentinel.conf --sentinel

/Users/chyzhong/01-worktools/08-redis-6.0.8/bin/redis-server /Users/chyzhong/01-worktools/08-redis-6.0.8-cluster/1-conf/redis-26372-sentinel.conf --sentinel

/Users/chyzhong/01-worktools/08-redis-6.0.8/bin/redis-server /Users/chyzhong/01-worktools/08-redis-6.0.8-cluster/1-conf/redis-26373-sentinel.conf --sentinel

另外配置内部会自动生成 sentinel myid 值。

2.4 测试redis运行情况

2.4.1 测试主库

cd /Users/chyzhong/01-worktools/08-redis-6.0.8/bin

##########################################################################################

->redis-cli -h 192.168.0.101 -p 6371 -a gzst2022
->info replication
或者:
-> redis-cli -h 192.168.0.101 -p 6371 -a gzst2022 info replication

# Replication
role:master
connected_slaves:2
slave0:ip=192.168.0.101,port=6372,state=online,offset=51471,lag=1
slave1:ip=192.168.0.101,port=6373,state=online,offset=51471,lag=1
master_replid:ed3f6f9e37f49953cfc89bb7957630414b3dd8e6
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:51626
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:51626

2.4.2 测试从库

->redis-cli -h 192.168.0.101 -p 6372 -a gzst2022 info replication

->redis-cli -h 192.168.0.101 -p 6373 -a gzst2022 info replication

# Replication
role:slave
master_host:192.168.0.101
master_port:6371
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0
slave_repl_offset:68503
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:ed3f6f9e37f49953cfc89bb7957630414b3dd8e6
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:68503
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:68503

### 

# Replication
role:slave
master_host:192.168.0.101
master_port:6371
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0
slave_repl_offset:73057
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:ed3f6f9e37f49953cfc89bb7957630414b3dd8e6
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:73057
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:15
repl_backlog_histlen:73043

2.4.3 测试哨兵

##########################################################################################

->redis-cli -h 192.168.0.101 -p 26371 -a gzst2022
->info sentinel
或者:
--> redis-cli -h 192.168.0.101 -p 26371 -a gzst2022 info sentinel

异常:
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=sdown,address=192.168.0.101:6371,slaves=0,sentinels=1

正常:
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=192.168.0.101:6371,slaves=2,sentinels=3
##########################################################################################

->redis-cli -h 192.168.0.101 -p 26372 -a gzst2022
->info sentinel
或者:
-> redis-cli -h 192.168.0.101 -p 26372 -a gzst2022 info sentinel

异常:
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=sdown,address=192.168.0.101:6371,slaves=0,sentinels=1

正常:
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=192.168.0.101:6371,slaves=2,sentinels=3
##########################################################################################

->redis-cli -h 192.168.0.101 -p 26373 -a gzst2022
->info sentinel
或者:
-> redis-cli -h 192.168.0.101 -p 26373 -a gzst2022 info sentinel

异常:
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=sdown,address=192.168.0.101:6371,slaves=0,sentinels=1

正常:
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=192.168.0.101:6371,slaves=2,sentinels=3

2.4.4 telnet 测试端口

telnet 192.168.0.101 26371

telnet 192.168.0.101 26372

telnet 192.168.0.101 26373

2.5 异常

2.5.1 命令异常

1. status=sdown.....,slaves=0,sentinels=1
	是因为哨兵配置文件没有配置sentinel auth-pass mymaster gzst2022
	
2. redis哨兵启动报错No such master with specified name
原因是配置的顺序,也就是我们监听的时候,是需要先配置监听master,给master取一个名字叫mymaster,才能配置这个认证节点的密码。但是认配置是密码在前面,监听配置在后面,这样就会报这个错,调整一下即可。

2.5.2 Java异常

1. NOAUTH Authentication required.. Trying next one.
解决:哨兵不要设置密码。

2. 警告: Cannot get master address from sentinel running @ 192.168.0.101:26372. Reason: redis.clients.jedis.exceptions.JedisDataException: NOAUTH Authentication required.. Trying next one.
Exception in thread "main" redis.clients.jedis.exceptions.JedisConnectionException: All sentinels down, cannot determine where is mymaster master is running...

2.6 应用

2.6.1 Java工具类

// 1.Redis连接池配置
		JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
		jedisPoolConfig.setMaxTotal(10);
		jedisPoolConfig.setMaxIdle(5);
		jedisPoolConfig.setMinIdle(5);
		
		// 2.设置sentinel 各个节点集合
		Set<String> sentinelSet = new HashSet<>();
		sentinelSet.add("192.168.0.101:26371");
		sentinelSet.add("192.168.0.101:26372");
		sentinelSet.add("192.168.0.101:26373");
		
		// 3.创建连接池
		//mymaster是我们配置给哨兵的服务名称, sentinelSet是哨兵集合, jedisPoolConfig是连接池配置, gzst2022是连接Redis服务器的密码
		JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinelSet, jedisPoolConfig, "gzst2022");
		
		// 4.获取客户端
		Jedis jedis = pool.getResource();
		
		// 5.执行两个命令
		jedis.set("mykey", "myvalue");
		String myvalue = jedis.get("mykey");
		// 6.打印信息
		System.out.println(myvalue);

2.6.2 SpringBoot配置

2.6.2.1 yaml配置
spring:
   redis:
    sentinel:
      nodes: 192.168.0.101:26371,192.168.0.101:26372,192.168.0.101:26373
      master: mymaster
    database: 6
    #连接超时时间
    timeout: 10000
    password: gzst2022
    jedis:
      pool:
        #最大连接数
        max-active: 8
        #最大阻塞等待时间(负数表示没限制)
        max-wait: -1
        #最大空闲
        max-idle: 8
        #最小空闲
        min-idle: 0
2.6.2.2 Java代码
2.6.2.2.1 配置类

注意:配置的密码。

package com.tiannan.demo.config;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.config.ReadMode;
import org.redisson.config.SentinelServersConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Configuration
@EnableAutoConfiguration
public class RedisConfig {

	@Autowired
	RedisProperties redisProperties;


	@Bean
	public JedisPoolConfig getRedisPoolConfig() {
		JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
		jedisPoolConfig.setMaxIdle(redisProperties.getJedis().getPool().getMaxIdle());
		jedisPoolConfig.setMaxIdle(redisProperties.getJedis().getPool().getMinIdle());
		jedisPoolConfig.setMaxWaitMillis(redisProperties.getJedis().getPool().getMaxWait().getSeconds());
		return jedisPoolConfig;
	}


	@Bean
	public JedisConnectionFactory jedisConnectionFactory(JedisPoolConfig jedisPoolConfig) {
		RedisSentinelConfiguration redisSentinelConfiguration = new RedisSentinelConfiguration();
		redisSentinelConfiguration.setMaster(redisProperties.getSentinel().getMaster());
		redisSentinelConfiguration.setDatabase(redisProperties.getDatabase());
		redisSentinelConfiguration.setSentinels(getSentinelNodes());
		redisSentinelConfiguration.setPassword(redisProperties.getPassword());
		JedisConnectionFactory objJedisConnectionFactory = new JedisConnectionFactory(redisSentinelConfiguration, jedisPoolConfig);
		return objJedisConnectionFactory;
	}

	@Bean
	public JedisSentinelPool getJedisPool() {
		Set<String> newNodes = new HashSet<>();
		for (int i = 0; i < redisProperties.getSentinel().getNodes().size(); i++) {
			newNodes.add(redisProperties.getSentinel().getNodes().get(i));
		}

		// 创建连接池
		JedisSentinelPool pool = new JedisSentinelPool(redisProperties.getSentinel().getMaster(), newNodes, getRedisPoolConfig(), Long.valueOf(redisProperties.getTimeout().toMillis()).intValue(), redisProperties.getPassword(), redisProperties.getDatabase());
		return pool;
	}

	@Bean
	public Set<RedisNode> getSentinelNodes() {
		Set<RedisNode> nodos = new HashSet<>();
		for (int i = 0; i < redisProperties.getSentinel().getNodes().size(); i++) {
			String[] split = redisProperties.getSentinel().getNodes().get(i).split(":");
			nodos.add(new RedisNode(split[0], Integer.parseInt(split[1])));
		}
		return nodos;
	}


	@Bean
	public RedissonClient createSentinelRedissonClient() {
		Config config = new Config();

		List<String> newNodes = new ArrayList<>();
		for (int i = 0; i < redisProperties.getSentinel().getNodes().size(); i++) {
			newNodes.add("redis://" + redisProperties.getSentinel().getNodes().get(i));
		}

		SentinelServersConfig serverConfig = config.useSentinelServers()
				.addSentinelAddress(newNodes.toArray(new String[0]))
				.setMasterName(this.redisProperties.getSentinel().getMaster())
				.setReadMode(ReadMode.SLAVE)
				.setTimeout(60000)
				.setRetryAttempts(3)
				.setRetryInterval(60000)
				//**此项务必设置为redisson解决之前bug的timeout问题关键*****
				.setPingConnectionInterval(60000)
				.setDatabase(redisProperties.getDatabase())
				.setPassword(redisProperties.getPassword());

		return Redisson.create(config);
	}
}
2.6.2.2.2 服务类
package com.tiannan.demo.service;

import java.util.Arrays;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisSentinelPool;

@Service
public class JedisService {
	Logger logger = LoggerFactory.getLogger(this.getClass());

	@Autowired
	JedisSentinelPool jedisSentinelPool;

	public Jedis getResource() {
		return jedisSentinelPool.getResource();
	}
	
	public void returnResource(Jedis jedis) {
		if(jedis != null){  
            //edisPool.returnResourceObject(jedis);
            jedis.close();
        }  
	}
	
	public void set(String key, String value) {
		Jedis jedis = null;
        try{  
            jedis = getResource();  
            jedis.set(key, value); 
            logger.info("Redis set success - " + key + ", value:" + value);  
        } catch (Exception e) {  
            e.printStackTrace();  
            logger.error("Redis set error: "+ e.getMessage() +" - " + key + ", value:" + value);  
        }finally{  
        	if(jedis!=null){
				returnResource(jedis);
			}
        }  
	}

	public String get(String key) {
		String result = null;  
        Jedis jedis=null;
        try{  
            jedis = getResource();  
            result = jedis.get(key);  
        } catch (Exception e) {  
            e.printStackTrace();  
            logger.error("Redis set error: "+ e.getMessage() +" - " + key + ", value:" + result);  
        }finally{  
        	if(jedis!=null){
				returnResource(jedis);
			}
        }  
        return result;  
	}
}
2.6.2.2.3 测试类
package com.tiannan.demo;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import com.tiannan.demo.service.JedisService;

@SpringBootTest
class SpringBootRedis04SentinelApplicationTests {

	@Autowired
	private JedisService jedisService;

	@Test
	public void test01() {
		jedisService.set("username", "张三");

		String sex = jedisService.get("username");

		System.out.println(sex); // 打印信息:张三
	}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值