主从复制问题的手动解决
主从复制 — master 节点宕机故障:如果 master 节点宕机,我们需要在剩下的 salve 节点中选择一个作为 master 节点,然后将其他的 slave 节点指向新的 master 节点
master 节点宕机前:
master 节点宕机,选出新的 master 节点,继续工作:
Redis Sentinel 架构
客户端从 sentinel 获取 redis 的信息:
sentinel 故障转移:
- 多个 sentinel 发现并确认 master 有问题
- 选举出一个 sentinel 作为领导
- 选出一个 slave 作为 master
- 通知其余 slave 成为新的 master 的 slave
- 通知客户端主从变化
- 等待老的 master 复活成为新 master 的 slave
Redis Sentinel 安装
Redis Sentinel 配置:
- 配置开启主从节点
- 配置开启sentinel监控主节点(sentinel是特殊的redis)
- 详细配置节点
示例(在同一台机器上进行配置,实际应该配置在不同的服务器上):
1、Redis 主节点 master 配置文件:redis-server redis-7000.conf
port 7000
daemonize yes
pidfile /var/run/redis-7000.pid
dir "/var/redis/"
dbfilename dump-7000.rdb
2、Redis 主节点 slave 配置文件:redis-server redis-7001.conf
port 7001
daemonize yes
pidfile /var/run/redis-7001.pid
dir "/var/redis/"
dbfilename dump-7001.rdb
slaveof 127.0.0.1 7000
3、sentinel 主要配置:redis-sentinel-26379.conf
port 26379
dir "/var/redis/sentinel/"
logfile "26379.log"
sentinel monitor mymaster 127.0.0.1 7000 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
客户端:
- 客户端遍历 Sentinel 节点集合,获取一个可用的 Sentinel 节点
- 执行:sentinel get-master-addr-by-name masterName,获取master节点的地址
- 客户端获取到sentinel返回的master节点信息后,会使用 role 或 role replication 进行一次验证该节点是否是 master 节点 ```java // 客户端需要的两个参数:Sentinel地址集合、masterName // 注意这不是代理模式
// master节点的名称
String masterName = “mymaster”;
// sentinel节点的地址
Set
JedisSentinelPool sentinelPool = new JedisSentinelPool( masterName, sentinelSet, jedisPoolConfig);
Random random = new Random();
int count = 0; for (; ; ) { try (Jedis jedis = sentinelPool.getResource();) { String key = “key-“ + random.nextInt(10000); String value = “value-“ + random.nextInt(10000); jedis.set(key, value); if (count % 100 == 0) { logger.info(“{} is key,{} is value”, key, value); } count++; TimeUnit.MILLISECONDS.sleep(10); } catch (Exception e) { logger.error(e.getMessage(), e); } } ```
三个定时任务:
1、每 10 s每个 sentinel 对 master 和 slave 执行 info
- 发现 slave 节点
- 确认主从关系
2、每 2 s每个 sentinel 通过 master 节点的 channel 交换信息(pub/sub)
- 通过 sentinel:hello 频道交互
- 交互对节点的“看法”和自身信息
3、每 1 s每个 sentinel 对其他 sentinel 和 redis 执行 ping
- 心跳检测,失败判定依据
主观下线和客观下线:
1、sentinel monitor
参数说明:
- masterName:master 节点的命名
- ip:master 节点的 IP,要用真实的 IP 地址而不要用回环地址(127.0.0.1)
- 主观下线:每个 sentinel 节点对 redis 节点失败的“偏见”
- 客观下线:所有 sentinel 节点的 redis 节点失败“达成共识”(超过 quorum 个同意)
注意事项:
- sentinel 节点要是基数
- quorum 要配置成 sentinel 节点数的一半 + 1
2、sentinel auth-pass
3、sentinel down-after-milliseconds
4、sentinel parallel-syncs mymaster 1:在故障转移时,该名称为mymaster的集群中同一时间点只允许1个节点进行复制
5、sentinel failover-timeout mymaster 180000:故障转移的超时时间
领导者选举:
- 原因:只有一个 sentinel 节点完成故障转移
- 选举:通过 sentinel is-master-down-by-addr 命令都希望成为领导者
步骤:
- 每个做主观下线的 Sentinel 节点向其他 Sentinel 节点发送命令,要求将它设置为领导者
- 收到命令的 Sentinel 节点如果没有同意通过其他 Sentinel 节点发送的命令,那么将同意该请求,否则拒绝
- 如果该 Sentinel 节点发现自己的票数已经超过 Sentinel 集合半数且超过quorum,那么它将成为领导者
- 如果此过程有多个 Sentinel 节点成为了领导者,那么将等待一段时间重新进行选举
故障转移:sentinel 领导者节点完成
- 从 slave 节点中选出一个“合适的”节点作为新的 master 节点
- 对上面的 slave 节点执行 slaveof no one 命令让其成为 master 节点
- 向剩余的 slave 节点发送命令,让它们成为新 master 节点的 slave 节点,复制规则和 parallel-syncs 参数有关
- 更新对原来 master 节点配置为 slave ,并保持着对其“关注”,当其恢复后命令它去复制新的master节点。
选择“合适的”slave节点:
- 选择 slave-priority(slave节点优先级)最高的 slave 节点,如果存在则返回,不存在则继续
- 选择复制偏移量最大的 slave 节点(复制的最完整),如果存在则返回,不存在则继续
- 选择 runld 最小的 slave 节点
常见开发运维问题:
1、节点运维:主节点、从节点、sentinel 节点
问题:
- 机器下线:例如过保等情况
- 机器性能不足:例如 CPU、内存、硬盘、网络等
- 节点自身故障::例如服务不稳定等
节点下线操作:
- 主节点:sentinel failover
- 从节点:临时下线还是永久下线,是否需要做清理工作,注意读写分离的情况
- sentinel:同从节点
节点上线操作:
- 主节点:sentinel failover 进行替换
- 从节点:slaveof
- sentinel 节点:参考其他 sentinel 节点启动
2、高可用读写分离:客户端需要监听三个消息
- +switch-master:切换主节点(从节点晋升主节点)
- +convert-to-slave:切换从节点(原主节点降为从节点)
- +sdown:主观下线