0032【Redis】简单玩玩从Redis单机扩展到一主二从三哨兵模式
二 一主二从三哨兵端口配置: 主:6371 从1:6372 从2:6373 哨兵1:26371 哨兵2:26372 哨兵3:263732.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.conf2.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变为replicaof2.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变为replicaof2.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.conf2.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.log2.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.log2.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.log2.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:516262.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:730432.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=32.4.4 telnet 测试端口
telnet 192.168.0.101 26371 telnet 192.168.0.101 26372 telnet 192.168.0.101 263732.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 各个节点集合 Set2.6.2 SpringBoot配置 2.6.2.1 yaml配置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);
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 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 getSentinelNodes() {
Set 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 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); // 打印信息:张三
}
}



