版本
CentOS 8.1.1911(VMWare)
redis 5.0.8
基本信息
服务器IP:192.168.31.68
Redis 端口:7000(主) 7001,7002(从) Sentinel端口:27000 27001 27002
- 关键代码或命令这样表示
配置Redis
- master7000.conf
bind 0.0.0.0
port 7000
daemonize yes dir /home/misty/redis-data/sentinel01 pidfile /var/run/redis_7000.pid logfile "7000.log" dbfilename dump7000.rdb
- slave7001.conf
bind 0.0.0.0
port 7001 daemonize yes dir /home/misty/redis-data/sentinel01 pidfile /var/run/redis_7001.pid logfile "7001.log" dbfilename dump7001.rdb slaveof 192.168.31.68 7000
- slave7002.conf
bind 0.0.0.0
port 7002 daemonize yes dir /home/misty/redis-data/sentinel01 pidfile /var/run/redis_7002.pid logfile "7002.log" dbfilename dump7002.rdb slaveof 192.168.31.68 7000
启动Redis服务
- 启动redis
redis-server master7000.conf
redis-server slave7001.conf redis-server slave7002.conf
验证服务已启动
$ ps -ef | grep redis-server | grep -v grep misty 4633 2639 0 03:16 ? 00:00:00 redis-server 0.0.0.0:7000 misty 4649 2639 0 03:16 ? 00:00:00 redis-server 0.0.0.0:7001 misty 4663 2639 0 03:16 ? 00:00:00 redis-server 0.0.0.0:7002
Redis自动建立主从关系
redis:7000> info replication
# Replication
role:master connected_slaves:2 slave0:ip=192.168.31.68,port=7001,state=online,offset=630,lag=0 slave1:ip=192.168.31.68,port=7002,state=online,offset=630,lag=1 master_replid:187ff0474ccd0303571db1ca94174c46c2476dba master_replid2:0000000000000000000000000000000000000000 master_repl_offset:630
可知master已获知两个slave节点信息。值得注意的是offset,主从节点通过offset确定是否已同步。
redis:7001> info replication
# Replication
role:slave master_host:192.168.31.68 master_port:7000 master_link_status:up master_last_io_seconds_ago:6 master_sync_in_progress:0 slave_repl_offset:882 slave_priority:100 slave_read_only:1 connected_slaves:0 master_replid:187ff0474ccd0303571db1ca94174c46c2476dba master_replid2:0000000000000000000000000000000000000000 master_repl_offset:882
这里要注意slave_priority,在sentinel模式下,如果master宕机,sentinel首先根据slave_priority决定把谁升格为master。
默认配置下,所有节点的slave_priority是一样的,因此会根据offset选择最大的。
如果还无法选出继任者,则选择runID最小的作为master(资历最老的)。
runID通过info server查看。
此时我们认为shutdown掉master节点,此时slave节点会显示master节点状态为down。slave节点不会自动升格为master。
# Replication
role:slave
master_host:192.168.31.68 master_port:7000 master_link_status:down master_last_io_seconds_ago:-1
重新启动master节点后状态恢复为up
配置Sentinel
- sentinel27000.conf
port 27000
daemonize yes
pidfile /var/run/redis-sentinel.pid logfile "sentinel27000.log" dir /home/misty/redis-data/sentinel01 sentinel monitor mymaster 192.168.31.68 7000 2 sentinel down-after-milliseconds mymaster 30000 sentinel parallel-syncs mymaster 1 sentinel failover-timeout mymaster 180000 sentinel deny-scripts-reconfig yes
由于配置文件仅端口号不同,因此只贴出一个配置文件。可以通过sed命令批量创建
- sentinel27001.conf
sed "s/27000/27001/g" sentinel27000.conf > sentinel27001.conf
我们会注意到,sentinel的配置信息中并没有标识出其他sentinel的存在,仅仅标识了master节点的信息。当sentinel服务启动后,sentinel节点之间会自动通过master节点感知到其他sentinel节点及slave节点的存在。
sentinel启动后会修改配置文件,建议备份配置文件。
- 启动sentinel
redis-sentinel sentinel27000.conf
redis-sentinel sentinel27001.conf redis-sentinel sentinel27002.conf
验证sentinel启动成功:
> ps -ef | grep redis-sentinel | grep -v grep misty 5516 2639 0 03:59 ? 00:00:00 redis-sentinel *:27000 [sentinel] misty 5528 2639 0 04:00 ? 00:00:00 redis-sentinel *:27001 [sentinel] misty 5539 2639 0 04:00 ? 00:00:00 redis-sentinel *:27002 [sentinel]
使用redis-cli连接到任意一个sentinel,运行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=ok,address=192.168.31.68:7000,slaves=2,sentinels=3
一个sentinel群组可以管理多个redis主从群组,通过master:name区分
测试主从自动切换
我们shutdown掉7000节点,稍等片刻,会发现主节点已经切换到了7001节点。
sentinel:27000> info sentinel
...
master0:name=mymaster,status=ok,address=192.168.31.68:7001,slaves=2,sentinels=3
显示slaves仍然有两个,当查看7001节点时发现slave只剩一个7002了
redis:7001> info replication
# Replication
...
slave0:ip=192.168.31.68,port=7002,state=online,offset=227471,lag=0
重启redis:7000服务后,它自动被设置为redis:7001的slave
redis:7001> info replication
# Replication
...
slave0:ip=192.168.31.68,port=7002,state=online,offset=299880,lag=0 slave1:ip=192.168.31.68,port=7000,state=online,offset=299880,lag=1
完成
至此,一个基本的Redis Sentinel群组搭建完成。
redis sentinel节点只负责监控,不负责增删改查等命令的转发,客户端依然需要连接到实际的Redis master节点上进行操作。(不同于Cluster)
附录:Java连接Redis Sentinel
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import redis.clients.jedis.JedisSentinelPool;
import java.util.HashSet;
public class Sentinel {
public static void main(String[] args) { var poolConfig = new GenericObjectPoolConfig<>(); poolConfig.setMaxTotal(10); var sentinels = new HashSet<String>(); sentinels.add("192.168.31.68:27000"); sentinels.add("192.168.31.68:27001"); sentinels.add("192.168.31.68:27002"); var sentinelPool = new JedisSentinelPool("mymaster", sentinels, poolConfig, 30000); try (var jedis = sentinelPool.getResource()) { jedis.set("hello", "world"); System.out.println(jedis.get("hello")); } catch (Exception e) { e.printStackTrace(); } } }
如果Redis无法连接,请修改服务器防火墙,开放相关端口
客户端原理
- 选择一个可用的Sentinel节点
- 访问sentinel获取master的信息:sentinel get-master-addr-by-name mymaster
- 验证master节点:role
- 创建连接池
- 监听sentinel,发现master节点变更后重建连接池