Redis故障主从切换演示
Redis 2.4之后的版本开始集成了Sentinel,用于监控redis集群中 Master状态的工具,是Redis的高可用性解决方案。
sentinel 系统可以监视一个或者多个master节点,以及这些master节点的所有从节点;当某个master节点下线时,自动将该master下的某个从节点升级为master替代已下线的master节点继续处理请求。集群中的其他redis服务器自动指向新的master同步数据。
一般建议sentinel采取奇数台,防止某一台sentinel无法连接到master导致误切换。
Sentinel当前最新的稳定版本称为Sentinel 2,随着redis2.8的安装包一起发行。安装完Redis2.8后,可以在redis2.8/src/里找到Redis-sentinel的启动脚本
snetinel的状态会被持久化地写入sentinel的配置文件中。每次当收到一个新的配置时,或者新创建一个配置时,配置会被持久化到硬盘中,并带上配置的版本戳。这意味着,可以安全的停止和重启sentinel进程。
sentinel内部有3个定时任务:
1、每个sentinel每10秒会对master和slave发送info命令,两个目的:
a)发现slave节点
b)确认主从关系
2、每2秒每个sentinel通过master节点的channel交换信息(pub/sub)。master节点上有一个发布订阅的频道(__sentinel__:hello)。sentinel节点通过__sentinel__:hello频道进行信息交换(对节点的"看法"和自身的信息),达成共识。
3、每1秒每个sentinel对其他sentinel和redis节点执行ping操作(相互监控),这个其实是一个心跳检测,是失败判定的依据。
主观下线:
所谓主观下线(Subjectively Down, 简称 SDOWN)指的是单个Sentinel实例对服务器做出的下线判断,即单个sentinel认为某个服务下线(有可能是接收不到订阅,之间的网络不通等等原因)。
主观下线就是说如果服务器在down-after-milliseconds给定的毫秒数之内, 对 Sentinel 发送的 PING 命令没有回复, 或者返回一个错误, 那么 Sentinel 将这个服务器标记为主观下线。
客观下线:
客观下线(Objectively Down, 简称 ODOWN)指的是多个 Sentinel 实例在对同一个服务器做出 SDOWN 判断, 并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后, 得出的服务器下线判断,然后开启failover。
客观下线条件只适用于主服务器: 对于任何其他类型的 Redis 实例, Sentinel 在将它们判断为下线前不需要进行协商, 所以从服务器或者其他 Sentinel 永远不会达到客观下线条件。只要一个 Sentinel 发现某个主服务器进入了客观下线状态, 这个 Sentinel 就可能会被其他 Sentinel 推选出, 并对失效的主服务器执行自动故障迁移操作。
单机启动三个实例,一主两从。创建三个目录,分别是6379、6380、6381,创建conf、log、db三个目录,并拷贝redis.conf到对应的conf目录下
(master)修改6379/conf 目录下的redis.conf 配置
daemonize yes <== daemon进程运行
pidfile /Users/onlyone/software/redis/6379/redis.pid <== 进程id存放文件
port 6379 <== 端口
logfile /Users/onlyone/software/redis/6379/log/redis.log <== 日志目录
dir /Users/onlyone/software/redis/6379/db/ <== db目录
(slave) 修改6380/conf 目录下的redis.conf 配置
daemonize yes <== daemon进程运行
pidfile /Users/onlyone/software/redis/6380/redis.pid <== 进程id存放文件
port 6380 <== 端口
logfile /Users/onlyone/software/redis/6380/log/redis.log <== 日志目录
dir /Users/onlyone/software/redis/6380/db/ <== db目录
slaveof 127.0.0.1 6379 <== master机器
(slave) 修改6381/conf 目录下的redis.conf 配置
daemonize yes <== daemon进程运行
pidfile /Users/onlyone/software/redis/6381/redis.pid <== 进程id存放文件
port 6381 <== 端口
logfile /Users/onlyone/software/redis/6381/log/redis.log <== 日志目录
dir /Users/onlyone/software/redis/6381/db/ <== db目录
slaveof 127.0.0.1 6379 <== master机器
启动实例
./redis-server /Users/onlyone/software/redis/6379/conf/redis.conf &
./redis-server /Users/onlyone/software/redis/6380/conf/redis.conf &
./redis-server /Users/onlyone/software/redis/6381/conf/redis.conf &
查看进程信息
ps -ef|grep redis
501 32933 1 0 10:24上午 ?? 0:00.25 ./redis-server 127.0.0.1:6380
501 32986 1 0 10:27上午 ?? 0:00.09 ./redis-server 127.0.0.1:6381
501 32880 12633 0 10:22上午 ttys000 0:00.43 ./redis-server *:6379
查看master节点信息
./redis-cli -p 6379 "info"
。。。省略。。。
\# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=518,lag=1
slave1:ip=127.0.0.1,port=6381,state=online,offset=518,lag=1
master_replid:38605ae9c8d326685b9d114b31efffc405b54129
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:518
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:518
。。。省略。。。
查看slave(6380)节点信息
./redis-cli -p 6380 "info"
。。。省略。。。
\# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:10
master_sync_in_progress:0
slave_repl_offset:658
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:38605ae9c8d326685b9d114b31efffc405b54129
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:658
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:658
。。。省略。。。
主库写数据
➜ src ./redis-cli -p 6379
127.0.0.1:6379> set name tom
OK
127.0.0.1:6379> get name
"tom"
127.0.0.1:6379>
查看从库同步数据
➜ src ./redis-cli -p 6380
127.0.0.1:6380> get name
"tom"
127.0.0.1:6380>
主从切换
修改 /Users/onlyone/software/redis/sentinel/sentinel.conf 配置:
// 指定sentinel去监视一个名为mymaster的Master,Master的IP地址为127.0.0.1,端口 6379,只要有一个sentinel监听到主观下线就发起切换
sentinel monitor mymaster 127.0.0.1 6379 1
// 指定Sentinel判定Master断线的时间。(单位为毫秒,判定为主观下线SDOWN)
sentinel down-after-milliseconds mymaster 6000
启动一个哨兵进程:
./redis-server /Users/onlyone/software/redis/sentinel/sentinel.conf --sentinel &
查看进程:
➜ ~ ps -ef|grep redis
501 40383 1 0 9:38下午 ?? 0:02.92 ./redis-server 127.0.0.1:6380
501 40392 1 0 9:38下午 ?? 0:02.92 ./redis-server 127.0.0.1:6381
501 41238 1 0 10:03下午 ?? 0:00.82 ./redis-server 127.0.0.1:6379
501 41486 40536 0 10:15下午 ttys000 0:00.18 ./redis-server *:26379 [sentinel]
501 41010 40297 0 9:56下午 ttys003 0:00.01 ./redis-cli -p 6381
501 40523 40441 0 9:40下午 ttys004 0:00.02 ./redis-cli -p 6380
501 41502 40922 0 10:16下午 ttys005 0:00.01 ./redis-cli -p 6379
将6379端口的redis 进程(master)kill掉,Sentinel监控台的日志:
41486:X 21 Nov 22:17:25.082 # +sdown master mymaster 127.0.0.1 6379
41486:X 21 Nov 22:17:25.082 # +odown master mymaster 127.0.0.1 6379 #quorum 1/1
41486:X 21 Nov 22:17:25.082 # +new-epoch 1
41486:X 21 Nov 22:17:25.082 # +try-failover master mymaster 127.0.0.1 6379
41486:X 21 Nov 22:17:25.083 # +vote-for-leader 9dfae48ecf5b4cacda8053c138660b89eecf124e 1
41486:X 21 Nov 22:17:25.083 # +elected-leader master mymaster 127.0.0.1 6379
41486:X 21 Nov 22:17:25.083 # +failover-state-select-slave master mymaster 127.0.0.1 6379
41486:X 21 Nov 22:17:25.159 # +selected-slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
41486:X 21 Nov 22:17:25.159 * +failover-state-send-slaveof-noone slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
41486:X 21 Nov 22:17:25.229 * +failover-state-wait-promotion slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
41486:X 21 Nov 22:17:25.682 # +promoted-slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
41486:X 21 Nov 22:17:25.682 # +failover-state-reconf-slaves master mymaster 127.0.0.1 6379
41486:X 21 Nov 22:17:25.775 * +slave-reconf-sent slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
41486:X 21 Nov 22:17:26.697 * +slave-reconf-inprog slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
41486:X 21 Nov 22:17:26.697 * +slave-reconf-done slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
41486:X 21 Nov 22:17:26.780 # +failover-end master mymaster 127.0.0.1 6379
// 选举 6381 为新的master
41486:X 21 Nov 22:17:26.780 # +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6381
// 6380作为slave,监听主节点master
41486:X 21 Nov 22:17:26.780 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6381
// 6379作为slave,监听主节点master
41486:X 21 Nov 22:17:26.780 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381
// 6379 依然处于主观下线
41486:X 21 Nov 22:17:32.840 # +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381
重新把6379 redis启动
41486:X 21 Nov 22:40:01.164 # -sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381
41486:X 21 Nov 22:40:11.153 * +convert-to-slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381