不過推薦可以看大陸有很多牛逼得前輩文章寫得不錯
那這次實驗的配置有4台host
- 1台Redis Sentinel,IP為192.168.126.136 Port 26379
- 1台Redis Master,IP為192.168.126.133 Port 6379
- 2台Redis Slave,IP為192.168.126.134 Port 6380和192.168.126.135 Port 6381
配置如下
# Overcommit memory setting
vi /etc/sysctl.conf
vm.overcommit_memory = 1
# Reboot
reboot
# Edit Redis config
vi /etc/redis.conf
Master(192.168.126.133 6379)
# Protected mode
protected-mode yes
# Bind IP
bind 192.168.126.133 127.0.0.1
# Port 6379
port 6379
# Daemon
daemonize yes
supervised systemd
# PID
pidfile "/var/run/redis_6379.pid"
# Master password
masterauth "password"
# Min slave to write
min-slaves-to-write 1
# network delay max
min-slaves-max-lag 10
# Password
requirepass "password"
Slave 1(192.168.126.134 6380)
# Protected mode
protected-mode yes
# Bind IP
bind 192.168.126.134 127.0.0.1
# Port 6380
port 6380
# Daemon
daemonize yes
supervised systemd
# PID
pidfile "/var/run/redis_6380.pid"
# Master password
masterauth "password"
# Min slave to write
min-slaves-to-write 1
# network delay max
min-slaves-max-lag 10
# Password
requirepass "password"
# Master = 192.168.126.133 6379
slaveof 192.168.126.133 6379
Slave 2(192.168.126.135)
# Protected mode
protected-mode yes
# Bind IP
bind 192.168.126.135 127.0.0.1
# Port 6381
port 6381
# Daemon
daemonize yes
supervised systemd
# PID
pidfile "/var/run/redis_6381.pid"
# Master密碼
masterauth "password"
# Min slave to write
min-slaves-to-write 1
# network delay max
min-slaves-max-lag 10
# Password
requirepass "password"
# Master = 192.168.126.133 6379
slaveof 192.168.126.133 6379
# Add Redis to firewall
firewall-cmd --add-port=6379/tcp --permanent
firewall-cmd --add-port=6380/tcp --permanent
firewall-cmd --add-port=6381/tcp --permanent
firewall-cmd --reload
# Start Redis
redis-server /etc/redis.conf
# Show Redis replication
redis-cli -h 192.168.126.133 -p 6379 -a password info replication
redis-cli -h 192.168.126.134 -p 6380 -a password info replication
redis-cli -h 192.168.126.135 -p 6381 -a password info replication
# Show log and status
cat /var/log/redis/redis.log
# Edit Redis Sentinel
vi /etc/redis-sentinel.conf
# Bind IP
bind 192.168.126.136 127.0.0.1
# Protected mode
protected-mode yes
# Port 26379
port 26379
# Dir
dir "/tmp"
sentinel myid 784086e6b6db80a7ba2af6a3cefeccb0f4d54978
# Sentinel監視該mymaster Redis如果該服務器失效則需要1個Sentinel則可判定為失效
# Sentinel數量不足則自動故障遷移機制則不會啟動
sentinel monitor mymaster 192.168.126.133 6379 1
# 5秒內Redis沒有回應則是視為Subjectively down(SDOWN)
sentinel down-after-milliseconds mymaster 5000
# 100秒內沒有failover成功就算失敗。
sentinel failover-timeout mymaster 100000
# Redis Sentinel password
sentinel auth-pass mymaster password
# Add Redis Sentinel to firewall
firewall-cmd --add-port=26379/tcp --permanent
firewall-cmd --reload
# Start sentinel
# redis-sentinel /etc/redis-sentinel.conf
# equals
# redis-server /etc/redis-sentinel.conf --sentinel
redis-server /etc/redis-sentinel.conf --sentinel
# Show log and status
cat /var/log/redis/sentinel.log
# Show Redis Sentinel Info
redis-cli -h 192.168.126.136 -p 26379 -a password info Sentinel
Java程式碼:
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;
import redis.clients.jedis.exceptions.JedisConnectionException;
import java.io.*;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
public class RedisTest {
private JedisSentinelPool pool;
private Jedis jedis;
private static Properties properties = new Properties();
static {
InputStream stream = null;
final File f = new File("Redis.properties");
try {
stream = f.exists() ? new FileInputStream("Redis.properties") : new FileInputStream("src/main/resources/Redis.properties");
properties.load(stream);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static final JedisPoolConfig getJedisPoolConfig() {
final int MAX_ACTIVE = Integer.parseInt(properties.getProperty("redis.pool.maxActive"));
final int MAX_IDLE = Integer.parseInt(properties.getProperty("redis.pool.maxIdle"));
final int MIN_IDLE = Integer.parseInt(properties.getProperty("redis.pool.minIdle"));
final long MAX_WAIT_MILLIS = Long.parseLong(properties.getProperty("redis.pool.maxWaitMillis"));
final int NUM_TESTS_PER_EVICTION_RUN = Integer.parseInt(properties.getProperty("redis.pool.numTestsPerEvictionRun"));
final long TIME_BETWEEN_EVICTION_RUNS_MILLIS = Long.parseLong(properties.getProperty("redis.pool.timeBetweenEvictionRunsMillis"));
final long MIN_EVICTABLE_IDLE_TIME_MILLIS = Long.parseLong(properties.getProperty("redis.pool.timeBetweenEvictionRunsMillis"));
final long SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS = Long.parseLong(properties.getProperty("redis.pool.softMinEvictableIdleTimeMillis"));
final boolean TEST_ON_BORROW = Boolean.parseBoolean(properties.getProperty("redis.pool.testOnBorrow"));
final boolean TEST_WHILE_IDLE = Boolean.parseBoolean(properties.getProperty("redis.pool.testWhileIdle"));
final boolean TEST_ON_RETURN = Boolean.parseBoolean(properties.getProperty("redis.pool.testOnReturn"));
final boolean BLOCK_WHEN_EXHAUSTED = Boolean.parseBoolean(properties.getProperty("redis.pool.blockWhenExhausted"));
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(MAX_ACTIVE);
config.setMaxIdle(MAX_IDLE);
config.setMinIdle(MIN_IDLE);
config.setMaxWaitMillis(MAX_WAIT_MILLIS);
config.setNumTestsPerEvictionRun(NUM_TESTS_PER_EVICTION_RUN);
config.setTimeBetweenEvictionRunsMillis(TIME_BETWEEN_EVICTION_RUNS_MILLIS);
config.setMinEvictableIdleTimeMillis(MIN_EVICTABLE_IDLE_TIME_MILLIS);
config.setSoftMinEvictableIdleTimeMillis(SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS);
config.setTestOnBorrow(TEST_ON_BORROW);
config.setTestWhileIdle(TEST_WHILE_IDLE);
config.setTestOnReturn(TEST_ON_RETURN);
config.setBlockWhenExhausted(BLOCK_WHEN_EXHAUSTED);
return config;
}
public static RedisTest getInstance() {
return new RedisTest();
}
private RedisTest() {
final String MASTER_NAME = properties.getProperty("redis.masterName");
final String PASSWORD = properties.getProperty("redis.password", "");
final Set<String> SENTINELS = new HashSet<String>(Arrays.asList(properties.getProperty("redis.sentinels").toString().split(";")));
this.pool = new JedisSentinelPool(MASTER_NAME, SENTINELS, getJedisPoolConfig(), PASSWORD);
try {
this.jedis = this.pool.getResource();
}catch (JedisConnectionException ex){
ex.printStackTrace();
}
}
public String set(String key, String value) {
return this.jedis.set(key, value);
}
public String get(String key) {
return this.jedis.get(key);
}
}
Redis.properties:
redis.masterName=mymaster
redis.sentinels=192.168.126.136:26379
redis.password=password
redis.pool.maxActive=128
redis.pool.maxIdle=10
redis.pool.minIdle=1
redis.pool.maxWaitMillis=3000
redis.pool.numTestsPerEvictionRun=50
redis.pool.timeBetweenEvictionRunsMillis=3000
redis.pool.minEvictableIdleTimeMillis=1800000
redis.pool.softMinEvictableIdleTimeMillis=10000
redis.pool.testOnBorrow=true
redis.pool.testWhileIdle=true
redis.pool.testOnReturn=true
redis.pool.blockWhenExhausted=true
Master還是133時將其Master關閉
則Master角色會從133轉移至其中一台的Slave
那也可以從下面的路徑來得知目前服務器的狀況
/var/log/redis/sentinel.log
/var/log/redis/redis.log
參考資料:
https://redislabs.com/redis-features/high-availability
https://redis.io/topics/virtual-memory
https://redis.io/topics/admin
https://www.cnblogs.com/youzhibing/p/8466491.html
https://blog.csdn.net/li_haijiang/article/details/76602826
https://blog.csdn.net/liutingxu1/article/details/17116107
https://blog.csdn.net/wzy0623/article/details/82706614
https://medium.com/androvideo/redis-ha-%E9%85%8D%E7%BD%AE-c82ea641a43d
https://dotblogs.com.tw/supershowwei/2016/02/03/123740
https://www.itread01.com/content/1545470113.html
https://codertw.com/%E8%B3%87%E6%96%99%E5%BA%AB/17596/
https://segmentfault.com/a/1190000002680804