主从复制问题的手动解决

主从复制 — master 节点宕机故障:如果 master 节点宕机,我们需要在剩下的 salve 节点中选择一个作为 master 节点,然后将其他的 slave 节点指向新的 master 节点

master 节点宕机前:
image.png
master 节点宕机,选出新的 master 节点,继续工作:
image.png

Redis Sentinel 架构

客户端从 sentinel 获取 redis 的信息:
image.png

sentinel 故障转移:

  1. 多个 sentinel 发现并确认 master 有问题
  2. 选举出一个 sentinel 作为领导
  3. 选出一个 slave 作为 master
  4. 通知其余 slave 成为新的 master 的 slave
  5. 通知客户端主从变化
  6. 等待老的 master 复活成为新 master 的 slave

Redis Sentinel 安装

Redis Sentinel 配置:

  1. 配置开启主从节点
  2. 配置开启sentinel监控主节点(sentinel是特殊的redis)
  3. 详细配置节点

示例(在同一台机器上进行配置,实际应该配置在不同的服务器上):
image.png

1、Redis 主节点 master 配置文件:redis-server redis-7000.conf

  1. port 7000
  2. daemonize yes
  3. pidfile /var/run/redis-7000.pid
  4. dir "/var/redis/"
  5. dbfilename dump-7000.rdb

2、Redis 主节点 slave 配置文件:redis-server redis-7001.conf

  1. port 7001
  2. daemonize yes
  3. pidfile /var/run/redis-7001.pid
  4. dir "/var/redis/"
  5. dbfilename dump-7001.rdb
  6. slaveof 127.0.0.1 7000

3、sentinel 主要配置:redis-sentinel-26379.conf

  1. port 26379
  2. dir "/var/redis/sentinel/"
  3. logfile "26379.log"
  4. sentinel monitor mymaster 127.0.0.1 7000 2
  5. sentinel down-after-milliseconds mymaster 30000
  6. sentinel parallel-syncs mymaster 1
  7. sentinel failover-timeout mymaster 180000

客户端:

  1. 客户端遍历 Sentinel 节点集合,获取一个可用的 Sentinel 节点
  2. 执行:sentinel get-master-addr-by-name masterName,获取master节点的地址
  3. 客户端获取到sentinel返回的master节点信息后,会使用 role 或 role replication 进行一次验证该节点是否是 master 节点 ```java // 客户端需要的两个参数:Sentinel地址集合、masterName // 注意这不是代理模式

// master节点的名称 String masterName = “mymaster”; // sentinel节点的地址 Set sentinelSet = new HashSet<>(); sentinelSet.add(“127.0.0.1:26379”); sentinelSet.add(“127.0.0.1:26380”); sentinelSet.add(“127.0.0.1:26381”); // 连接池参数 JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); jedisPoolConfig.setMaxTotal(10); jedisPoolConfig.setMaxIdle(10);

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 频道交互
  • 交互对节点的“看法”和自身信息

image.png

3、每 1 s每个 sentinel 对其他 sentinel 和 redis 执行 ping

  • 心跳检测,失败判定依据

image.png

主观下线和客观下线:
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 :设置连接 master 和 slave 时的密码,注意sentinel不支持分别为 master 和 slave 设置不同的密码,因此 master 和 slave 的密码应该设置相同

3、sentinel down-after-milliseconds :每个sentinel 在连续 ping 30000ms 不通后认为有问题

4、sentinel parallel-syncs mymaster 1:在故障转移时,该名称为mymaster的集群中同一时间点只允许1个节点进行复制

5、sentinel failover-timeout mymaster 180000:故障转移的超时时间

领导者选举:

  • 原因:只有一个 sentinel 节点完成故障转移
  • 选举:通过 sentinel is-master-down-by-addr 命令都希望成为领导者

步骤:

  1. 每个做主观下线的 Sentinel 节点向其他 Sentinel 节点发送命令,要求将它设置为领导者
  2. 收到命令的 Sentinel 节点如果没有同意通过其他 Sentinel 节点发送的命令,那么将同意该请求,否则拒绝
  3. 如果该 Sentinel 节点发现自己的票数已经超过 Sentinel 集合半数且超过quorum,那么它将成为领导者
  4. 如果此过程有多个 Sentinel 节点成为了领导者,那么将等待一段时间重新进行选举

故障转移:sentinel 领导者节点完成

  1. 从 slave 节点中选出一个“合适的”节点作为新的 master 节点
  2. 对上面的 slave 节点执行 slaveof no one 命令让其成为 master 节点
  3. 向剩余的 slave 节点发送命令,让它们成为新 master 节点的 slave 节点,复制规则和 parallel-syncs 参数有关
  4. 更新对原来 master 节点配置为 slave ,并保持着对其“关注”,当其恢复后命令它去复制新的master节点。

选择“合适的”slave节点:

  1. 选择 slave-priority(slave节点优先级)最高的 slave 节点,如果存在则返回,不存在则继续
  2. 选择复制偏移量最大的 slave 节点(复制的最完整),如果存在则返回,不存在则继续
  3. 选择 runld 最小的 slave 节点

常见开发运维问题:
1、节点运维:主节点、从节点、sentinel 节点
问题:

  • 机器下线:例如过保等情况
  • 机器性能不足:例如 CPU、内存、硬盘、网络等
  • 节点自身故障::例如服务不稳定等

节点下线操作:

  • 主节点:sentinel failover
  • 从节点:临时下线还是永久下线,是否需要做清理工作,注意读写分离的情况
  • sentinel:同从节点

节点上线操作:

  • 主节点:sentinel failover 进行替换
  • 从节点:slaveof
  • sentinel 节点:参考其他 sentinel 节点启动

2、高可用读写分离:客户端需要监听三个消息

  • +switch-master:切换主节点(从节点晋升主节点)
  • +convert-to-slave:切换从节点(原主节点降为从节点)
  • +sdown:主观下线

image.png