这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战
主从复制
replicaof masterip masterport
读写分离, 数据容灾
全量同步
- 同步快照
- 同步写缓冲
- 同步增量阶段
增量同步
- slave完成初始化开始正常工作, master每执行一个写命令就会向slave发送相同的写命令
心跳检测
命令传播阶段, 从服务器默认以每秒一次的频率向主服务器发送命令,
replconf ack <replcation_off>
作用:
-
检测主从的连接状态
-
辅助实现min-slaves
min-replicas-to-write 3 min-replicas-max-lag 10从服务器的数量少于3个或者三个从服务器的延迟都大于或等于10秒, 主服务器拒绝执行写命令
-
检测命令丢失
哨兵模式
部署
Master
daemonize yes
#bind 127.0.0.1
protected-mode no
Slave
replicaof 127.0.0.1 6379
Sentinel
daemonize yes
# 主节点的ip port quorum 当quorum个哨兵认为主节点失联, 客观下线
sentinel monitor mymaster 127.0.0.1 6379 2
# 主节点 requirepass 123
sentinel auth-pass mymaster 123
# 多少毫秒后,主节点没有应答哨兵, 主观下线 默认30秒
sentinel down-after-milliseconds mymaster 30000
#数字越小,完成failover所需时间越长,数字越大, 越多的slave因为replication不可用, 保证每次只有一个slave处于不能处理命令的状态
sentinel parallel-syncs mymaster 1
# 故障转移时间 默认三分钟
sentinel failover-timeout mymaster 180000
-
启动并初始化Sentinel
sentinel 实例不会持久化, 会创建两个连向主服务器的网络连接。
命令连接: 用于向主服务器发送命令,并接收响应
订阅连接: 用于订阅主服务器的-sentinel-:hello品道
-
获取主服务器信息
每10s向被监控的主服务器发送info, 获取主服务器和从服务器信息
-
获取从服务器信息
每10s向从服务器发送info
-
向主服务器和从服务器发送消息(订阅)
每2s向所有的主从服务器所订阅的-sentinel-:hello频道上发送消息, 消息中会携带sentinel信息和主服务器信息
-
接收来自主服务器和从服务器的频道信息
sentinel订阅-sentinel-:hello
-
检测主观下线状态
sentinel每秒向所有建立了命令连接的实例发送PING命令
实例在down-after-milliseconds毫秒内返回无效回复(除了+PONG、-LOADING、-MASTERDOWN外),如果无回复,就认为是主观下线(SDown)
-
检查客观下线状态
当认为是主观下线后, Sentinel向同时监控这个主服务器的Sentinel发送查询命令, 如果达到quorum数量的Sentinel实例都认为主观下线,则主服务器被判定为客观下线(ODown)
故障转移
Raft: leader, follower, candidate
通过raft选举出Leader Sentinel后, 执行故障转移操作。
- 失效Master的其中一个Slave升级为Master,其他slave复制新的master
- 客户端连接失效的master,集群返回新master的地址
- master和slave服务器切换后,master的redis.conf,slave的redis.conf和sentinel.conf的配置文件发生相应改变。
主服务器选择规则:
- 过滤掉主观下线节点
- 选择slave-priority最高的节点
- 选择复制偏移量最大的节点
- 选择run_id最小的节点
Cluster
去中心化, sharding, replication, failover
Gossip
通信协议,传播消息的方式。
一个节点周期性随机选择一些节点,并把信息传递给这些节点。信息会周期性的传递给N个目标节点。 N被称为fanout(删除)。
消息主要包含 meet, ping, pong, fail ,publish等
slot
平均分配,连续分配。【0-16383】
value-slot-节点
对key使用crc16算法结果后对16384求余数, 这样大致均等的映射到不同的节点
port 7001
cluster-enable yes
./redis-cli --cluster create 192.168.72.128:7001 192.168.72.128:7002 192.168.72.128:7003 192.168.72.128:7004 192.168.72.128:7005 192.168.72.128:7006 --cluster-replicas 1
cluster nodes
cluster slots
cluster keyslot name
moved重定向 槽已确认迁移
ask重定向 槽正在迁移
进行集群扩容和缩容,对槽进行迁移
迁移
- B的slot状态设为importing
- A的slot状态设为migrating
- 向A发送migrate命令
- cluster setslot重新设置槽位
扩容:
./redis-cli --cluster add-node 192.168.72.128:7007 192.168.72.128:7001
./redis-cli --cluster reshard 192.168.72.128:7007
./redis-cli --cluster add-node 192.168.72.128:7008 192.168.72.128:7007 -- cluster-slave --cluster-master-id 6ff20bf463c954e977b213f0e36f3efc02bd53d6
缩容:
./redis-cli --cluster del-node 192.168.127.128:7008 6be94480315ab0dd2276a7f70c82c578535d6666
容灾
故障检测
每个节点定期向其他节点发送PING消息,一定时间(cluster-node-timeout),A没收到B的PONG回应, A将B标识为pfail, 后续发送时会带上B的pfail信息,通知其他节点, 标记B为pfail的个数大于集群主节点个数的一半, B被标记为fail, A向整个集群广播,节点下线。
从节点选举
raft,每个从节点,都根据自己对master复制数据的offset,来设置一个选举时间,offset越大(复制数据越多)的从节点,选举时间越靠前,优先进行选举。slave 通过向其他master发送FAILVOER_AUTH_REQUEST 消息发起竞选,master 收到后回复FAILOVER_AUTH_ACK 消息告知是否同意。slave 发送FAILOVER_AUTH_REQUEST 前会将currentEpoch 自增,并将最新的Epoch 带入到FAILOVER_AUTH_REQUEST 消息中,如果自己未投过票,则回复同意,否则回复拒绝。所有的Master开始slave选举投票,给要进行选举的slave进行投票,如果大部分master node(N/2 +1)都投票给了某个从节点,那么选举通过,那个从节点可以切换成master。
RedisCluster失效的判定:1、集群中半数以上的主节点都宕机(无法投票)2、宕机的主节点的从节点也宕机了(slot槽分配不连续)
手动切换
人工故障切换是预期的操作,而非发生了真正的故障,目的是以一种安全的方式(数据无丢失)将当前master节点和其中一个slave节点(执行cluster-failover的节点)交换角色
1、向从节点发送cluster failover 命令(slaveof no one)
2、从节点告知其主节点要进行手动切换(CLUSTERMSG_TYPE_MFSTART)
3、主节点会阻塞所有客户端命令的执行(10s)
4、从节点从主节点的ping包中获得主节点的复制偏移量
5、从节点复制达到偏移量,发起选举、统计选票、赢得选举、升级为主节点并更新配置
6、切换完成后,原主节点向所有客户端发送moved指令重定向到新的主节点
以上是在主节点在线情况下。
如果主节点下线了,则采用cluster failover force或cluster failover takeover 进行强制切换。