Redis 主从集群与哨兵机制
Redis的QPS可以达到10W/s,基本情况下单机已经可以满足了。当对性能要求更高时,一般都会采用集群方案来解决。
集群方案可以避免
- 当数据量过大时性能瓶颈是硬件资源,而直接扩展硬件则利用率太低了;
- 当Redis服务宕机时,对服务访问会产生严重影响;
- 当Redis服务硬件损坏时,会造成不可恢复的灾难影响。
集群方案有很多,最简单的就是主从模式+哨兵模式。
一主二从示例
配置文件
port 6379
slave:使用默认的配置文件,修改端口配置,新增主从节点配置
- 端口号
port 6380
- 主节点配置: 注意这是v6.0.6。由于master-salve关键字被投票变更了,原来的slave改为replica
# replicaof <masterip> <masterport>
replicaof 127.0.0.1 6379
- 如果master节点有密码,则需要配置密码
# masterauth <master-password>
# masterauth 123456
启动命令
master
redis-server.exe
slave1
redis-server.exe ../redis-6380.conf
salve2
redis-server.exe ../redis-6381.conf
节点查询
127.0.0.1:0>info Replication
"# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=2114,lag=0
slave1:ip=127.0.0.1,port=6381,state=online,offset=2114,lag=0
master_replid:229fe4bb558e5d5d60888cd22b8c4899595c9215
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:2114
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:2114
"
在主从集群中,主节点是读、写操作,从节点是只读操作。该属性可在配置文件中配置
127.0.0.1:0>get msg
"hello word"
127.0.0.1:0>set str str
"OK"
localhost-slave-6380:0>get msg
"hello word"
localhost-slave-6380:0>set msg a
"READONLY You can't write against a read only replica. "
主要参数
repl_timeout: 主从超时时间:默认60(s)
在RedisServer启动时,根据配置的config_hz启动定时任务serverCron。在这个任务中存在
run_with_period(1000) replicationCron();
在这个每秒执行主从复制的定时任务中,存在server.repl_timeout超时取消。
- 主从连接超时
- 主从数据传输超时
- 主从无数据传输超时
repl-disable-tcp-nodelay: 主从复制数据传输时TCP是否禁用TCP_NODELAY。默认no
if (server.repl_disable_tcp_nodelay)
connDisableTcpNoDelay(c->conn);
主从复制流程
- 服务启动从replicaof获取master节点地址
- 建立master节点通信
- master节点生成RDB文件,传输给salve节点,完成初次的全量复制
- 在master生成RDB期间,新接收的命令会缓存起来,在传输时一起传输到salve
- salve对接收到的RDB文件进行恢复,完成复制
- 后续节点通过命令传播机制,主节点执行的命令会传播到从节点再次执行
sentinel(哨兵)
sentinel(哨兵):用来监控、管理Redis集群。主要解决的是主从复制集群方案中出现节点宕机后主从问题。
多个sentinel不仅监控集群中的每一个Server节点,还监控其他的sentinel节点。
主要功能
-
监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
-
提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
-
自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作, 它会将失效主服务器的其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器; 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。
sentinel监控图示
配置文件
哨兵1(sentinel.conf)
port 26379
dir "../../logs"
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
哨兵2(sentinel-26380.conf)
port 26380
dir "../../logs"
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
哨兵3(sentinel-26381.conf)
port 26381
dir "../../logs"
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
启动
可以用redis-sentinel
命令启动,也可以用
redis-server --sentinel
命令启动
哨兵1:只监控到了主从
redis-sentinel.exe ../sentinel.conf
1075:X 04 Aug 2020 14:25:46.742 # Sentinel ID is cc5d8ced88de425bb2d2fa6a267e3ad86923b12e
1075:X 04 Aug 2020 14:25:46.742 # +monitor master mymaster 127.0.0.1 6379 quorum 2
1075:X 04 Aug 2020 14:25:46.746 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
1075:X 04 Aug 2020 14:25:46.749 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
哨兵2:监控到了主从和已经启动的哨兵1
redis-sentinel.exe ../sentinel-26380.conf
1076:X 04 Aug 2020 14:26:53.428 # Sentinel ID is 73f58d1263bb36298e11399fc6c63f98fdc6f64a
1076:X 04 Aug 2020 14:26:53.428 # +monitor master mymaster 127.0.0.1 6379 quorum 2
1076:X 04 Aug 2020 14:26:53.433 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
1076:X 04 Aug 2020 14:26:53.436 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
1076:X 04 Aug 2020 14:26:54.222 * +sentinel sentinel cc5d8ced88de425bb2d2fa6a267e3ad86923b12e 127.0.0.1 26379 @ mymaster 127.0.0.1 6379
哨兵3:监控到了主从和已启动的哨兵1和哨兵2
redis-server.exe ../sentinel-26381.conf --sentinel
1077:X 04 Aug 2020 14:28:46.733 # Sentinel ID is c6a316bc1e0e18ad086c0a32de506f26abfbc393
1077:X 04 Aug 2020 14:28:46.733 # +monitor master mymaster 127.0.0.1 6379 quorum 2
1077:X 04 Aug 2020 14:28:46.740 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
1077:X 04 Aug 2020 14:28:46.743 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
1077:X 04 Aug 2020 14:28:47.960 * +sentinel sentinel 73f58d1263bb36298e11399fc6c63f98fdc6f64a 127.0.0.1 26380 @ mymaster 127.0.0.1 6379
1077:X 04 Aug 2020 14:28:48.644 * +sentinel sentinel cc5d8ced88de425bb2d2fa6a267e3ad86923b12e 127.0.0.1 26379 @ mymaster 127.0.0.1 6379
从启动日志也可以看出来,哨兵不仅监控Redis主从,还监控其他哨兵。哨兵1和哨兵2最后也会监控哨兵3
启动验证
sentinel:0>info replication
"# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=66246,lag=0
slave1:ip=127.0.0.1,port=6381,state=online,offset=66246,lag=0
master_replid:229fe4bb558e5d5d60888cd22b8c4899595c9215
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:66246
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:66246
"
sentinel:0>
故障迁移
关闭master节点验证,等待30秒
哨兵1:
1075:X 04 Aug 2020 14:46:03.706 # +sdown master mymaster 127.0.0.1 6379
1075:X 04 Aug 2020 14:46:03.717 # +new-epoch 1
1075:X 04 Aug 2020 14:46:03.722 # +vote-for-leader c6a316bc1e0e18ad086c0a32de506f26abfbc393 1
1075:X 04 Aug 2020 14:46:03.786 # +odown master mymaster 127.0.0.1 6379 #quorum 3/2
1075:X 04 Aug 2020 14:46:03.787 # Next failover delay: I will not start a failover before Tue Aug 4 14:52:04 2020
1075:X 04 Aug 2020 14:46:04.956 # +config-update-from sentinel c6a316bc1e0e18ad086c0a32de506f26abfbc393 127.0.0.1 26381 @ mymaster 127.0.0.1 6379
1075:X 04 Aug 2020 14:46:04.957 # +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6380
1075:X 04 Aug 2020 14:46:04.959 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
1075:X 04 Aug 2020 14:46:04.959 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
1075:X 04 Aug 2020 14:46:34.962 # +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
哨兵2:
1076:X 04 Aug 2020 14:46:03.393 # +sdown master mymaster 127.0.0.1 6379
1076:X 04 Aug 2020 14:46:03.719 # +new-epoch 1
1076:X 04 Aug 2020 14:46:03.722 # +vote-for-leader c6a316bc1e0e18ad086c0a32de506f26abfbc393 1
1076:X 04 Aug 2020 14:46:04.526 # +odown master mymaster 127.0.0.1 6379 #quorum 3/2
1076:X 04 Aug 2020 14:46:04.530 # Next failover delay: I will not start a failover before Tue Aug 4 14:52:03 2020
1076:X 04 Aug 2020 14:46:04.955 # +config-update-from sentinel c6a316bc1e0e18ad086c0a32de506f26abfbc393 127.0.0.1 26381 @ mymaster 127.0.0.1 6379
1076:X 04 Aug 2020 14:46:04.956 # +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6380
1076:X 04 Aug 2020 14:46:04.957 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
1076:X 04 Aug 2020 14:46:04.957 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
1076:X 04 Aug 2020 14:46:34.987 # +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
哨兵3:
1077:X 04 Aug 2020 14:46:03.611 # +sdown master mymaster 127.0.0.1 6379
1077:X 04 Aug 2020 14:46:03.703 # +odown master mymaster 127.0.0.1 6379 #quorum 2/2
1077:X 04 Aug 2020 14:46:03.703 # +new-epoch 1
1077:X 04 Aug 2020 14:46:03.703 # +try-failover master mymaster 127.0.0.1 6379
1077:X 04 Aug 2020 14:46:03.708 # +vote-for-leader c6a316bc1e0e18ad086c0a32de506f26abfbc393 1
1077:X 04 Aug 2020 14:46:03.724 # cc5d8ced88de425bb2d2fa6a267e3ad86923b12e voted for c6a316bc1e0e18ad086c0a32de506f26abfbc393 1
1077:X 04 Aug 2020 14:46:03.726 # 73f58d1263bb36298e11399fc6c63f98fdc6f64a voted for c6a316bc1e0e18ad086c0a32de506f26abfbc393 1
1077:X 04 Aug 2020 14:46:03.811 # +elected-leader master mymaster 127.0.0.1 6379
1077:X 04 Aug 2020 14:46:03.812 # +failover-state-select-slave master mymaster 127.0.0.1 6379
1077:X 04 Aug 2020 14:46:03.909 # +selected-slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
1077:X 04 Aug 2020 14:46:03.910 * +failover-state-send-slaveof-noone slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
1077:X 04 Aug 2020 14:46:03.980 * +failover-state-wait-promotion slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
1077:X 04 Aug 2020 14:46:04.870 # +promoted-slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
1077:X 04 Aug 2020 14:46:04.871 # +failover-state-reconf-slaves master mymaster 127.0.0.1 6379
1077:X 04 Aug 2020 14:46:04.950 * +slave-reconf-sent slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
1077:X 04 Aug 2020 14:46:05.865 # -odown master mymaster 127.0.0.1 6379
1077:X 04 Aug 2020 14:46:05.975 * +slave-reconf-inprog slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
1077:X 04 Aug 2020 14:46:05.975 * +slave-reconf-done slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
1077:X 04 Aug 2020 14:46:06.051 # +failover-end master mymaster 127.0.0.1 6379
1077:X 04 Aug 2020 14:46:06.053 # +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6380
1077:X 04 Aug 2020 14:46:06.056 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
1077:X 04 Aug 2020 14:46:06.058 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
1077:X 04 Aug 2020 14:46:36.101 # +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
日志说明
为了能看懂以上启动日志,展示部分的日志说明
+reset-master <instance details> :主服务器已被重置。
+slave <instance details> :一个新的从服务器已经被 Sentinel 识别并关联。
+failover-state-reconf-slaves <instance details> :故障转移状态切换到了 reconf-slaves 状态。
+failover-detected <instance details> :另一个 Sentinel 开始了一次故障转移操作,或者一个从服务器转换成了主服务器。
+slave-reconf-sent <instance details> :领头(leader)的 Sentinel 向实例发送了 SLAVEOF host port 命令,为实例设置新的主服务器。
+slave-reconf-inprog <instance details> :实例正在将自己设置为指定主服务器的从服务器,但相应的同步过程仍未完成。
+slave-reconf-done <instance details> :从服务器已经成功完成对新主服务器的同步。
-dup-sentinel <instance details> :对给定主服务器进行监视的一个或多个 Sentinel 已经因为重复出现而被移除 —— 当 Sentinel 实例重启的时候,就会出现这种情况。
+sentinel <instance details> :一个监视给定主服务器的新 Sentinel 已经被识别并添加。
+sdown <instance details> :给定的实例现在处于主观下线状态。
-sdown <instance details> :给定的实例已经不再处于主观下线状态。
+odown <instance details> :给定的实例现在处于客观下线状态。
-odown <instance details> :给定的实例已经不再处于客观下线状态。
+new-epoch <instance details> :当前的纪元(epoch)已经被更新。
+try-failover <instance details> :一个新的故障迁移操作正在执行中,等待被大多数 Sentinel 选中(waiting to be elected by the majority)。
+elected-leader <instance details> :赢得指定纪元的选举,可以进行故障迁移操作了。
+failover-state-select-slave <instance details> :故障转移操作现在处于 select-slave 状态 —— Sentinel 正在寻找可以升级为主服务器的从服务器。
no-good-slave <instance details> :Sentinel 操作未能找到适合进行升级的从服务器。Sentinel 会在一段时间之后再次尝试寻找合适的从服务器来进行升级,又或者直接放弃执行故障转移操作。
selected-slave <instance details> :Sentinel 顺利找到适合进行升级的从服务器。
failover-state-send-slaveof-noone <instance details> :Sentinel 正在将指定的从服务器升级为主服务器,等待升级功能完成。
failover-end-for-timeout <instance details> :故障转移因为超时而中止,不过最终所有从服务器都会开始复制新的主服务器(slaves will eventually be configured to replicate with the new master anyway)。
failover-end <instance details> :故障转移操作顺利完成。所有从服务器都开始复制新的主服务器了。
+switch-master <master name> <oldip> <oldport> <newip> <newport> :配置变更,主服务器的 IP 和地址已经改变。 这是绝大多数外部用户都关心的信息。
在哨兵3中存在主从切换的信息
+switch-master mymaster 127.0.0.1 6379 127.0.0.1 6380
结合日志说明,主服务器从6379切换到了6380。查看新的主服务器信息如下
localhost-slave-6380:0>info replication
"# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6381,state=online,offset=504998,lag=1
master_replid:3a299441d6f9bb65ad21c7dc0dfc569004202b5a
master_replid2:4cc7a8b732eadcf56dafb1bd0506a85fc6cccf78
master_repl_offset:505264
second_repl_offset:448871
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:505264
"
此时再启动6379服务器
哨兵1:
1075:X 04 Aug 2020 15:01:44.393 # -sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
1075:X 04 Aug 2020 15:01:54.400 * +convert-to-slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
哨兵2:
1076:X 04 Aug 2020 15:01:44.493 # -sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
哨兵3:
1077:X 04 Aug 2020 15:01:44.719 # -sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
可以看出来重新启动后,原来的主服务器变成了从服务器,而且所有哨兵都监控到了,并标记为非主观下线状态。