为什么至少三个哨兵_一文带你了解Redis哨兵模式和高可用集群解析(万字长文)...-程序员宅基地

技术标签: 为什么至少三个哨兵  

前言

Redis 主从复制 模式下,一旦 主节点 由于故障不能提供服务,需要手动将 从节点 晋升为 主节点,同时还要通知 客户端 更新 主节点地址,这种故障处理方式从一定程度上是无法接受的。Redis 2.8 以后提供了 Redis Sentinel 哨兵机制 来解决这个问题。

3a0fb5ecd6b9f93b80c7516759f76058.png

正文

1. Redis高可用概述

在 Web 服务器中,高可用 是指服务器可以 正常访问 的时间,衡量的标准是在 多长时间 内可以提供正常服务(99.9%、99.99%、99.999% 等等)。在 Redis 层面,高可用 的含义要宽泛一些,除了保证提供 正常服务(如 主从分离快速容灾技术 等),还需要考虑 数据容量扩展数据安全 等等。

在 Redis 中,实现 高可用 的技术主要包括 持久化复制哨兵集群,下面简单说明它们的作用,以及解决了什么样的问题:

  • 持久化:持久化是 最简单的 高可用方法。它的主要作用是 数据备份,即将数据存储在 硬盘,保证数据不会因进程退出而丢失。
  • 复制:复制是高可用 Redis 的基础,哨兵集群 都是在 复制基础 上实现高可用的。复制主要实现了数据的多机备份以及对于读操作的负载均衡和简单的故障恢复。缺陷是故障恢复无法自动化、写操作无法负载均衡、存储能力受到单机的限制。
  • 哨兵:在复制的基础上,哨兵实现了 自动化故障恢复。缺陷是 写操作 无法 负载均衡存储能力 受到 单机 的限制。
  • 集群:通过集群,Redis 解决了 写操作 无法 负载均衡 以及 存储能力 受到 单机限制 的问题,实现了较为 完善高可用方案

2. Redis Sentinel的基本概念

Redis Sentinel 是 Redis 高可用 的实现方案。Sentinel 是一个管理多个 Redis 实例的工具,它可以实现对 Redis 的 监控通知自动故障转移。下面先对 Redis Sentinel 的 基本概念 进行简单的介绍。

基本名词说明:

f6e741001a0ec02623acc13ced8ebc21.png

如图所示,Redis 的 主从复制模式 和 Sentinel 高可用架构 的示意图:

b8aea53a240cacd9d2a8cc1482a82d13.png

3. Redis主从复制的问题

Redis 主从复制 可将 主节点 数据同步给 从节点,从节点此时有两个作用:

  1. 一旦 主节点宕机从节点 作为 主节点备份 可以随时顶上来。
  2. 扩展 主节点读能力,分担主节点读压力。
44bfccc8314bcf70cf139e18ddada303.png

主从复制 同时存在以下几个问题:

  1. 一旦 主节点宕机从节点 晋升成 主节点,同时需要修改 应用方主节点地址,还需要命令所有 从节点复制 新的主节点,整个过程需要 人工干预
  2. 主节点写能力 受到 单机的限制
  3. 主节点存储能力 受到 单机的限制
  4. 原生复制 的弊端在早期的版本中也会比较突出,比如:Redis 复制中断 后,从节点 会发起 psync。此时如果 同步不成功,则会进行 全量同步主库 执行 全量备份 的同时,可能会造成毫秒或秒级的 卡顿

4. Redis Sentinel深入探究

4.1. Redis Sentinel的架构

4ada0b9933256b90c2cca4dedd6bf454.png

4.2. Redis Sentinel的主要功能

Sentinel 的主要功能包括 主节点存活检测主从运行情况检测自动故障转移 (failover)、主从切换。Redis 的 Sentinel 最小配置是 一主一从

Redis 的 Sentinel 系统可以用来管理多个 Redis 服务器,该系统可以执行以下四个任务:

  • 监控

Sentinel 会不断的检查 主服务器从服务器 是否正常运行。

  • 通知

当被监控的某个 Redis 服务器出现问题,Sentinel 通过 API 脚本管理员 或者其他的 应用程序 发送通知。

  • 自动故障转移

主节点 不能正常工作时,Sentinel 会开始一次 自动的 故障转移操作,它会将与 失效主节点主从关系 的其中一个 从节点 升级为新的 主节点,并且将其他的 从节点 指向 新的主节点

  • 配置提供者

在 Redis Sentinel 模式下,客户端应用 在初始化时连接的是 Sentinel 节点集合,从中获取 主节点 的信息。

4.3. 主观下线和客观下线

默认情况下,每个 Sentinel 节点会以 每秒一次 的频率对 Redis 节点和 其它 的 Sentinel 节点发送 PING 命令,并通过节点的 回复 来判断节点是否在线。

  • 主观下线

主观下线 适用于所有 主节点从节点。如果在 down-after-milliseconds 毫秒内,Sentinel 没有收到 目标节点 的有效回复,则会判定 该节点主观下线

  • 客观下线

客观下线 只适用于 主节点。如果 主节点 出现故障,Sentinel 节点会通过 sentinel is-master-down-by-addr命令,向其它 Sentinel 节点询问对该节点的 状态判断。如果超过 个数的节点判定 主节点 不可达,则该 Sentinel 节点会判断 主节点客观下线

4.4. Sentinel的通信命令

Sentinel 节点连接一个 Redis 实例的时候,会创建 cmd 和 pub/sub 两个 连接。Sentinel 通过 cmd 连接给 Redis发送命令,通过 pub/sub 连接到 Redis 实例上的其他 Sentinel 实例。

Sentinel 与 Redis 主节点从节点 交互的命令,主要包括:

09e8958655603b2a29e9f3dee81fb4be.png

Sentinel 与 Sentinel 交互的命令,主要包括:

fe88d74370e963a69584824ed141c131.png

4.5. Redis Sentinel的工作原理

每个 Sentinel 节点都需要 定期执行 以下任务:

  • 每个 Sentinel 以 每秒钟 一次的频率,向它所知的 主服务器从服务器 以及其他 Sentinel 实例 发送一个 PING 命令。
04011a52ebf066737707c13b64570182.png
  1. 如果一个 实例(instance)距离 最后一次 有效回复 PING 命令的时间超过 down-after-milliseconds 所指定的值,那么这个实例会被 Sentinel 标记为 主观下线
5a6b71cb260ccec23ff4c825a76bcde5.png
  1. 如果一个 主服务器 被标记为 主观下线,那么正在 监视 这个 主服务器 的所有 Sentinel 节点,要以 每秒一次 的频率确认 主服务器 的确进入了 主观下线 状态。
fac2189d7b7be5c3a2016c509e8b4460.png
  1. 如果一个 主服务器 被标记为 主观下线,并且有 足够数量 的 Sentinel(至少要达到 配置文件 指定的数量)在指定的 时间范围 内同意这一判断,那么这个 主服务器 被标记为 客观下线
b540267ec846e1cb04fd581385245ed7.png
  1. 在一般情况下, 每个 Sentinel 会以每 10 秒一次的频率,向它已知的所有 主服务器从服务器 发送 INFO 命令。当一个 主服务器 被 Sentinel 标记为 客观下线 时,Sentinel 向 下线主服务器 的所有 从服务器 发送 INFO 命令的频率,会从 10 秒一次改为 每秒一次
328869faab7f3f5f895fe92baf2bee8b.png
  1. Sentinel 和其他 Sentinel 协商 主节点 的状态,如果 主节点 处于 SDOWN 状态,则投票自动选出新的 主节点。将剩余的 从节点 指向 新的主节点 进行 数据复制
d9245331cef383c7656092ba361d4732.png
  1. 当没有足够数量的 Sentinel 同意 主服务器 下线时, 主服务器客观下线状态 就会被移除。当 主服务器 重新向 Sentinel 的 PING 命令返回 有效回复 时,主服务器主观下线状态 就会被移除。
5c54ebbb2285ed89dacb3301cee56226.png

注意:一个有效的 PING 回复可以是:+PONG、-LOADING 或者 -MASTERDOWN。如果 服务器 返回除以上三种回复之外的其他回复,又或者在 指定时间 内没有回复 PING 命令, 那么 Sentinel 认为服务器返回的回复 无效(non-valid)。

5. Redis Sentinel搭建

5.1. Redis Sentinel的部署须知

  1. 一个稳健的 Redis Sentinel 集群,应该使用至少 三个 Sentinel 实例,并且保证讲这些实例放到 不同的机器 上,甚至不同的 物理区域
  2. Sentinel 无法保证 强一致性
  3. 常见的 客户端应用库 都支持 Sentinel。
  4. Sentinel 需要通过不断的 测试观察,才能保证高可用。

5.2. Redis Sentinel的配置文件

# 哨兵sentinel实例运行的端口,默认26379 port 26379# 哨兵sentinel的工作目录dir ./# 哨兵sentinel监控的redis主节点的 ## ip:主机ip地址## port:哨兵端口号## master-name:可以自己命名的主节点名字(只能由字母A-z、数字0-9 、这三个字符".-_"组成。)## quorum:当这些quorum个数sentinel哨兵认为master主节点失联 那么这时 客观上认为主节点失联了 # sentinel monitor  sentinel monitor mymaster 127.0.0.1 6379 2# 当在Redis实例中开启了requirepass ,所有连接Redis实例的客户端都要提供密码。# sentinel auth-pass  sentinel auth-pass mymaster 123456 # 指定主节点应答哨兵sentinel的最大时间间隔,超过这个时间,哨兵主观上认为主节点下线,默认30秒 # sentinel down-after-milliseconds sentinel down-after-milliseconds mymaster 30000 # 指定了在发生failover主备切换时,最多可以有多少个slave同时对新的master进行同步。这个数字越小,完成failover所需的时间就越长;反之,但是如果这个数字越大,就意味着越多的slave因为replication而不可用。可以通过将这个值设为1,来保证每次只有一个slave,处于不能处理命令请求的状态。# sentinel parallel-syncs sentinel parallel-syncs mymaster 1 # 故障转移的超时时间failover-timeout,默认三分钟,可以用在以下这些方面:## 1. 同一个sentinel对同一个master两次failover之间的间隔时间。 ## 2. 当一个slave从一个错误的master那里同步数据时开始,直到slave被纠正为从正确的master那里同步数据时结束。 ## 3. 当想要取消一个正在进行的failover时所需要的时间。## 4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来同步数据了# sentinel failover-timeout  sentinel failover-timeout mymaster 180000# 当sentinel有任何警告级别的事件发生时(比如说redis实例的主观失效和客观失效等等),将会去调用这个脚本。一个脚本的最大执行时间为60s,如果超过这个时间,脚本将会被一个SIGKILL信号终止,之后重新执行。# 对于脚本的运行结果有以下规则: ## 1. 若脚本执行后返回1,那么该脚本稍后将会被再次执行,重复次数目前默认为10。## 2. 若脚本执行后返回2,或者比2更高的一个返回值,脚本将不会重复执行。 ## 3. 如果脚本在执行过程中由于收到系统中断信号被终止了,则同返回值为1时的行为相同。# sentinel notification-script  sentinel notification-script mymaster /var/redis/notify.sh# 这个脚本应该是通用的,能被多次调用,不是针对性的。# sentinel client-reconfig-script sentinel client-reconfig-script mymaster /var/redis/reconfig.sh

5.3. Redis Sentinel的节点规划

f61d964b8fffd03b2ff913dd415e02c3.png

5.4. Redis Sentinel的配置搭建

5.4.1. Redis-Server的配置管理

分别拷贝三份 redis.conf 文件到 /usr/local/redis-sentinel 目录下面。三个配置文件分别对应 master、slave1 和 slave2 三个 Redis 节点的 启动配置

$ sudo cp /usr/local/redis-4.0.11/redis.conf /usr/local/redis-sentinel/redis-16379.conf$ sudo cp /usr/local/redis-4.0.11/redis.conf /usr/local/redis-sentinel/redis-26379.conf$ sudo cp /usr/local/redis-4.0.11/redis.conf /usr/local/redis-sentinel/redis-36379.conf

分别修改三份配置文件如下:

  • 主节点:redis-16379.conf
daemonize yespidfile /var/run/redis-16379.pidlogfile /var/log/redis/redis-16379.logport 16379bind 0.0.0.0timeout 300databases 16dbfilename dump-16379.dbdir ./redis-workdirmasterauth 123456requirepass 123456
  • 从节点1:redis-26379.conf
daemonize yespidfile /var/run/redis-26379.pidlogfile /var/log/redis/redis-26379.logport 26379bind 0.0.0.0timeout 300databases 16dbfilename dump-26379.dbdir ./redis-workdirmasterauth 123456requirepass 123456slaveof 127.0.0.1 16379
  • 从节点2:redis-36379.conf
daemonize yespidfile /var/run/redis-36379.pidlogfile /var/log/redis/redis-36379.logport 36379bind 0.0.0.0timeout 300databases 16dbfilename dump-36379.dbdir ./redis-workdirmasterauth 123456requirepass 123456slaveof 127.0.0.1 16379

如果要做 自动故障转移,建议所有的 redis.conf 都设置 masterauth。因为 自动故障 只会重写 主从关系,即 slaveof,不会自动写入 masterauth。如果 Redis 原本没有设置密码,则可以忽略。

5.4.2. Redis-Server启动验证

按顺序分别启动 16379,26379 和 36379 三个 Redis 节点,启动命令和启动日志如下:

Redis 的启动命令:

$ sudo redis-server /usr/local/redis-sentinel/redis-16379.conf$ sudo redis-server /usr/local/redis-sentinel/redis-26379.conf$ sudo redis-server /usr/local/redis-sentinel/redis-36379.conf

查看 Redis 的启动进程:

$ ps -ef | grep redis-server 0 7127 1 0 2:16下午 ?? 0:01.84 redis-server 0.0.0.0:16379  0 7133 1 0 2:16下午 ?? 0:01.73 redis-server 0.0.0.0:26379  0 7137 1 0 2:16下午 ?? 0:01.70 redis-server 0.0.0.0:36379 
 

查看 Redis 的启动日志:

  • 节点 redis-16379
$ cat /var/log/redis/redis-16379.log 7126:C 22 Aug 14:16:38.907 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo7126:C 22 Aug 14:16:38.908 # Redis version=4.0.11, bits=64, commit=00000000, modified=0, pid=7126, just started7126:C 22 Aug 14:16:38.908 # Configuration loaded7127:M 22 Aug 14:16:38.910 * Increased maximum number of open files to 10032 (it was originally set to 256).7127:M 22 Aug 14:16:38.912 * Running mode=standalone, port=16379.7127:M 22 Aug 14:16:38.913 # Server initialized7127:M 22 Aug 14:16:38.913 * Ready to accept connections7127:M 22 Aug 14:16:48.416 * Slave 127.0.0.1:26379 asks for synchronization7127:M 22 Aug 14:16:48.416 * Full resync requested by slave 127.0.0.1:263797127:M 22 Aug 14:16:48.416 * Starting BGSAVE for SYNC with target: disk7127:M 22 Aug 14:16:48.416 * Background saving started by pid 71347134:C 22 Aug 14:16:48.433 * DB saved on disk7127:M 22 Aug 14:16:48.487 * Background saving terminated with success7127:M 22 Aug 14:16:48.494 * Synchronization with slave 127.0.0.1:26379 succeeded7127:M 22 Aug 14:16:51.848 * Slave 127.0.0.1:36379 asks for synchronization7127:M 22 Aug 14:16:51.849 * Full resync requested by slave 127.0.0.1:363797127:M 22 Aug 14:16:51.849 * Starting BGSAVE for SYNC with target: disk7127:M 22 Aug 14:16:51.850 * Background saving started by pid 71387138:C 22 Aug 14:16:51.862 * DB saved on disk7127:M 22 Aug 14:16:51.919 * Background saving terminated with success7127:M 22 Aug 14:16:51.923 * Synchronization with slave 127.0.0.1:36379 succeeded

以下两行日志日志表明,redis-16379 作为 Redis 的 主节点,redis-26379 和 redis-36379 作为 从节点,从 主节点 同步数据。

7127:M 22 Aug 14:16:48.416 * Slave 127.0.0.1:26379 asks for synchronization7127:M 22 Aug 14:16:51.848 * Slave 127.0.0.1:36379 asks for synchronization
  • 节点 redis-26379
$ cat /var/log/redis/redis-26379.log 7132:C 22 Aug 14:16:48.407 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo7132:C 22 Aug 14:16:48.408 # Redis version=4.0.11, bits=64, commit=00000000, modified=0, pid=7132, just started7132:C 22 Aug 14:16:48.408 # Configuration loaded7133:S 22 Aug 14:16:48.410 * Increased maximum number of open files to 10032 (it was originally set to 256).7133:S 22 Aug 14:16:48.412 * Running mode=standalone, port=26379.7133:S 22 Aug 14:16:48.413 # Server initialized7133:S 22 Aug 14:16:48.413 * Ready to accept connections7133:S 22 Aug 14:16:48.413 * Connecting to MASTER 127.0.0.1:163797133:S 22 Aug 14:16:48.413 * MASTER  SLAVE sync started7133:S 22 Aug 14:16:48.414 * Non blocking connect for SYNC fired the event.7133:S 22 Aug 14:16:48.414 * Master replied to PING, replication can continue...7133:S 22 Aug 14:16:48.415 * Partial resynchronization not possible (no cached master)7133:S 22 Aug 14:16:48.417 * Full resync from master: 211d3b4eceaa3af4fe5c77d22adf06e1218e0e7b:07133:S 22 Aug 14:16:48.494 * MASTER  SLAVE sync: receiving 176 bytes from master7133:S 22 Aug 14:16:48.495 * MASTER  SLAVE sync: Flushing old data7133:S 22 Aug 14:16:48.496 * MASTER  SLAVE sync: Loading DB in memory7133:S 22 Aug 14:16:48.498 * MASTER  SLAVE sync: Finished with success
  • 节点 redis-36379
$ cat /var/log/redis/redis-36379.log 7136:C 22 Aug 14:16:51.839 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo7136:C 22 Aug 14:16:51.840 # Redis version=4.0.11, bits=64, commit=00000000, modified=0, pid=7136, just started7136:C 22 Aug 14:16:51.841 # Configuration loaded7137:S 22 Aug 14:16:51.843 * Increased maximum number of open files to 10032 (it was originally set to 256).7137:S 22 Aug 14:16:51.845 * Running mode=standalone, port=36379.7137:S 22 Aug 14:16:51.845 # Server initialized7137:S 22 Aug 14:16:51.846 * Ready to accept connections7137:S 22 Aug 14:16:51.846 * Connecting to MASTER 127.0.0.1:163797137:S 22 Aug 14:16:51.847 * MASTER  SLAVE sync started7137:S 22 Aug 14:16:51.847 * Non blocking connect for SYNC fired the event.7137:S 22 Aug 14:16:51.847 * Master replied to PING, replication can continue...7137:S 22 Aug 14:16:51.848 * Partial resynchronization not possible (no cached master)7137:S 22 Aug 14:16:51.850 * Full resync from master: 211d3b4eceaa3af4fe5c77d22adf06e1218e0e7b:147137:S 22 Aug 14:16:51.923 * MASTER  SLAVE sync: receiving 176 bytes from master7137:S 22 Aug 14:16:51.923 * MASTER  SLAVE sync: Flushing old data7137:S 22 Aug 14:16:51.924 * MASTER  SLAVE sync: Loading DB in memory7137:S 22 Aug 14:16:51.927 * MASTER  SLAVE sync: Finished with success

5.4.3. Sentinel的配置管理

分别拷贝三份 redis-sentinel.conf 文件到 /usr/local/redis-sentinel 目录下面。三个配置文件分别对应 master、slave1 和 slave2 三个 Redis 节点的 哨兵配置

$ sudo cp /usr/local/redis-4.0.11/sentinel.conf /usr/local/redis-sentinel/sentinel-16380.conf$ sudo cp /usr/local/redis-4.0.11/sentinel.conf /usr/local/redis-sentinel/sentinel-26380.conf$ sudo cp /usr/local/redis-4.0.11/sentinel.conf /usr/local/redis-sentinel/sentinel-36380.conf
  • 节点1:sentinel-16380.conf
protected-mode nobind 0.0.0.0port 16380daemonize yessentinel monitor master 127.0.0.1 16379 2sentinel down-after-milliseconds master 5000sentinel failover-timeout master 180000sentinel parallel-syncs master 1sentinel auth-pass master 123456logfile /var/log/redis/sentinel-16380.log
  • 节点2:sentinel-26380.conf
protected-mode nobind 0.0.0.0port 26380daemonize yessentinel monitor master 127.0.0.1 16379 2sentinel down-after-milliseconds master 5000sentinel failover-timeout master 180000sentinel parallel-syncs master 1sentinel auth-pass master 123456logfile /var/log/redis/sentinel-26380.log
  • 节点3:sentinel-36380.conf
protected-mode nobind 0.0.0.0port 36380daemonize yessentinel monitor master 127.0.0.1 16379 2sentinel down-after-milliseconds master 5000sentinel failover-timeout master 180000sentinel parallel-syncs master 1sentinel auth-pass master 123456logfile /var/log/redis/sentinel-36380.log

5.4.4. Sentinel启动验证

按顺序分别启动 16380,26380 和 36380 三个 Sentinel 节点,启动命令和启动日志如下:

$ sudo redis-sentinel /usr/local/redis-sentinel/sentinel-16380.conf$ sudo redis-sentinel /usr/local/redis-sentinel/sentinel-26380.conf$ sudo redis-sentinel /usr/local/redis-sentinel/sentinel-36380.conf

查看 Sentinel 的启动进程:

$ ps -ef | grep redis-sentinel 0 7954 1 0 3:30下午 ?? 0:00.05 redis-sentinel 0.0.0.0:16380 [sentinel]  0 7957 1 0 3:30下午 ?? 0:00.05 redis-sentinel 0.0.0.0:26380 [sentinel]  0 7960 1 0 3:30下午 ?? 0:00.04 redis-sentinel 0.0.0.0:36380 [sentinel] 

查看 Sentinel 的启动日志:

  • 节点 sentinel-16380
$ cat /var/log/redis/sentinel-16380.log 7953:X 22 Aug 15:30:27.245 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo7953:X 22 Aug 15:30:27.245 # Redis version=4.0.11, bits=64, commit=00000000, modified=0, pid=7953, just started7953:X 22 Aug 15:30:27.245 # Configuration loaded7954:X 22 Aug 15:30:27.247 * Increased maximum number of open files to 10032 (it was originally set to 256).7954:X 22 Aug 15:30:27.249 * Running mode=sentinel, port=16380.7954:X 22 Aug 15:30:27.250 # Sentinel ID is 69d05b86a82102a8919231fd3c2d1f21ce86e0007954:X 22 Aug 15:30:27.250 # +monitor master master 127.0.0.1 16379 quorum 27954:X 22 Aug 15:30:32.286 # +sdown sentinel fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7 127.0.0.1 36380 @ master 127.0.0.1 163797954:X 22 Aug 15:30:34.588 # -sdown sentinel fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7 127.0.0.1 36380 @ master 127.0.0.1 16379

sentinel-16380 节点的 Sentinel ID 为 69d05b86a82102a8919231fd3c2d1f21ce86e000,并通过 Sentinel ID 把自身加入 sentinel 集群中。

  • 节点 sentinel-26380
$ cat /var/log/redis/sentinel-26380.log 7956:X 22 Aug 15:30:30.900 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo7956:X 22 Aug 15:30:30.901 # Redis version=4.0.11, bits=64, commit=00000000, modified=0, pid=7956, just started7956:X 22 Aug 15:30:30.901 # Configuration loaded7957:X 22 Aug 15:30:30.904 * Increased maximum number of open files to 10032 (it was originally set to 256).7957:X 22 Aug 15:30:30.905 * Running mode=sentinel, port=26380.7957:X 22 Aug 15:30:30.906 # Sentinel ID is 21e30244cda6a3d3f55200bcd904d0877574e5067957:X 22 Aug 15:30:30.906 # +monitor master master 127.0.0.1 16379 quorum 27957:X 22 Aug 15:30:30.907 * +slave slave 127.0.0.1:26379 127.0.0.1 26379 @ master 127.0.0.1 163797957:X 22 Aug 15:30:30.911 * +slave slave 127.0.0.1:36379 127.0.0.1 36379 @ master 127.0.0.1 163797957:X 22 Aug 15:30:36.311 * +sentinel sentinel fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7 127.0.0.1 36380 @ master 127.0.0.1 16379

sentinel-26380 节点的 Sentinel ID 为 21e30244cda6a3d3f55200bcd904d0877574e506,并通过 Sentinel ID 把自身加入 sentinel 集群中。此时 sentinel 集群中已有 sentinel-16380 和 sentinel-26380 两个节点。

  • 节点 sentinel-36380
$ cat /var/log/redis/sentinel-36380.log 7959:X 22 Aug 15:30:34.273 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo7959:X 22 Aug 15:30:34.274 # Redis version=4.0.11, bits=64, commit=00000000, modified=0, pid=7959, just started7959:X 22 Aug 15:30:34.274 # Configuration loaded7960:X 22 Aug 15:30:34.276 * Increased maximum number of open files to 10032 (it was originally set to 256).7960:X 22 Aug 15:30:34.277 * Running mode=sentinel, port=36380.7960:X 22 Aug 15:30:34.278 # Sentinel ID is fd166dc66425dc1d9e2670e1f17cb94fe05f5fc77960:X 22 Aug 15:30:34.278 # +monitor master master 127.0.0.1 16379 quorum 27960:X 22 Aug 15:30:34.279 * +slave slave 127.0.0.1:26379 127.0.0.1 26379 @ master 127.0.0.1 163797960:X 22 Aug 15:30:34.283 * +slave slave 127.0.0.1:36379 127.0.0.1 36379 @ master 127.0.0.1 163797960:X 22 Aug 15:30:34.993 * +sentinel sentinel 21e30244cda6a3d3f55200bcd904d0877574e506 127.0.0.1 26380 @ master 127.0.0.1 16379 

sentinel-36380 节点的 Sentinel ID 为 fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7,并通过 Sentinel ID 把自身加入 sentinel 集群中。此时 sentinel 集群中已有 sentinel-16380,sentinel-26380 和 sentinel-36380 三个节点。

5.4.5. Sentinel配置刷新

  • 节点1:sentinel-16380.conf

sentinel-16380.conf 文件新生成如下的配置项:

# Generated by CONFIG REWRITEdir "/usr/local/redis-sentinel"sentinel config-epoch master 0sentinel leader-epoch master 0sentinel known-slave master 127.0.0.1 36379sentinel known-slave master 127.0.0.1 26379sentinel known-sentinel master 127.0.0.1 26380 21e30244cda6a3d3f55200bcd904d0877574e506sentinel known-sentinel master 127.0.0.1 36380 fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7sentinel current-epoch 0 

可以注意到,sentinel-16380.conf 刷新写入了 Redis 主节点关联的所有 从节点 redis-26379 和 redis-36379,同时写入了其余两个 Sentinel 节点 sentinel-26380 和 sentinel-36380 的 IP 地址,端口号 和 Sentinel ID。

# Generated by CONFIG REWRITEdir "/usr/local/redis-sentinel"sentinel config-epoch master 0sentinel leader-epoch master 0sentinel known-slave master 127.0.0.1 26379sentinel known-slave master 127.0.0.1 36379sentinel known-sentinel master 127.0.0.1 36380 fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7sentinel known-sentinel master 127.0.0.1 16380 69d05b86a82102a8919231fd3c2d1f21ce86e000sentinel current-epoch 0

可以注意到,sentinel-26380.conf 刷新写入了 Redis 主节点关联的所有 从节点 redis-26379 和 redis-36379,同时写入了其余两个 Sentinel 节点 sentinel-36380 和 sentinel-16380 的 IP 地址,端口号 和 Sentinel ID。

# Generated by CONFIG REWRITEdir "/usr/local/redis-sentinel"sentinel config-epoch master 0sentinel leader-epoch master 0sentinel known-slave master 127.0.0.1 36379sentinel known-slave master 127.0.0.1 26379sentinel known-sentinel master 127.0.0.1 16380 69d05b86a82102a8919231fd3c2d1f21ce86e000sentinel known-sentinel master 127.0.0.1 26380 21e30244cda6a3d3f55200bcd904d0877574e506sentinel current-epoch 0 

可以注意到,sentinel-36380.conf 刷新写入了 Redis 主节点关联的所有 从节点 redis-26379 和 redis-36379,同时写入了其余两个 Sentinel 节点 sentinel-16380 和 sentinel-26380 的 IP 地址,端口号 和 Sentinel ID。

5.5. Sentinel时客户端命令

  • 检查其他 Sentinel 节点的状态,返回 PONG 为正常。
> PING sentinel
  • 显示被监控的所有 主节点 以及它们的状态。
> SENTINEL masters
  • 显示指定 主节点 的信息和状态。
> SENTINEL master 
  • 显示指定 主节点 的所有 从节点 以及它们的状态。
> SENTINEL slaves 

返回指定 主节点 的 IP 地址和 端口。如果正在进行 failover 或者 failover 已经完成,将会显示被提升为 主节点从节点 的 IP 地址和 端口

> SENTINEL get-master-addr-by-name 
  • 重置名字匹配该 正则表达式 的所有的 主节点 的状态信息,清除它之前的 状态信息,以及 从节点 的信息。
> SENTINEL reset 
  • 强制当前 Sentinel 节点执行 failover,并且不需要得到其他 Sentinel 节点的同意。但是 failover 后会将 最新的配置 发送给其他 Sentinel 节点。
>SENTINEL failover 

6. Redis Sentinel故障切换与恢复

6.1. Redis CLI客户端跟踪

上面的日志显示,redis-16379 节点为 主节点,它的进程 ID 为 7127。为了模拟 Redis 主节点故障,强制杀掉这个进程。

$ kill -9 7127

使用 redis-cli 客户端命令进入 sentinel-16380 节点,查看 Redis 节点 的状态信息。

$ redis-cli -p 16380
  • 查看 Redis 主从集群的 主节点 信息。可以发现 redis-26379 晋升为 新的主节点
127.0.0.1:16380> SENTINEL master master 1) "name" 2) "master" 3) "ip" 4) "127.0.0.1" 5) "port" 6) "26379" 7) "runid" 8) "b8ca3b468a95d1be5efe1f50c50636cafe48c59f" 9) "flags"10) "master"11) "link-pending-commands"12) "0"13) "link-refcount"14) "1"15) "last-ping-sent"16) "0"17) "last-ok-ping-reply"18) "588"19) "last-ping-reply"20) "588"21) "down-after-milliseconds"22) "5000"23) "info-refresh"24) "9913"25) "role-reported"26) "master"27) "role-reported-time"28) "663171"29) "config-epoch"30) "1"31) "num-slaves"32) "2"33) "num-other-sentinels"34) "2"35) "quorum"36) "2"37) "failover-timeout"38) "180000"39) "parallel-syncs"40) "1" 

6.2. Redis Sentinel日志跟踪

查看任意 Sentinel 节点的日志如下:

7954:X 22 Aug 18:40:22.504 # +tilt #tilt mode entered7954:X 22 Aug 18:40:32.197 # +tilt #tilt mode entered7954:X 22 Aug 18:41:02.241 # -tilt #tilt mode exited7954:X 22 Aug 18:48:24.550 # +sdown master master 127.0.0.1 163797954:X 22 Aug 18:48:24.647 # +new-epoch 17954:X 22 Aug 18:48:24.651 # +vote-for-leader fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7 17954:X 22 Aug 18:48:25.678 # +odown master master 127.0.0.1 16379 #quorum 3/27954:X 22 Aug 18:48:25.678 # Next failover delay: I will not start a failover before Wed Aug 22 18:54:24 20187954:X 22 Aug 18:48:25.709 # +config-update-from sentinel fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7 127.0.0.1 36380 @ master 127.0.0.1 163797954:X 22 Aug 18:48:25.710 # +switch-master master 127.0.0.1 16379 127.0.0.1 263797954:X 22 Aug 18:48:25.710 * +slave slave 127.0.0.1:36379 127.0.0.1 36379 @ master 127.0.0.1 263797954:X 22 Aug 18:48:25.711 * +slave slave 127.0.0.1:16379 127.0.0.1 16379 @ master 127.0.0.1 263797954:X 22 Aug 18:48:30.738 # +sdown slave 127.0.0.1:16379 127.0.0.1 16379 @ master 127.0.0.1 263797954:X 22 Aug 19:38:23.479 # -sdown slave 127.0.0.1:16379 127.0.0.1 16379 @ master 127.0.0.1 26379 
  • 分析日志,可以发现 redis-16329 节点先进入 sdown 主观下线 状态。
+sdown master master 127.0.0.1 16379
  • 哨兵检测到 redis-16329 出现故障,Sentinel 进入一个 新纪元,从 0 变为 1。
+new-epoch 1
  • 三个 Sentinel 节点开始协商 主节点 的状态,判断其是否需要 客观下线
+vote-for-leader fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7 1
  • 超过 quorum 个数的 Sentinel 节点认为 主节点 出现故障,redis-16329 节点进入 客观下线 状态。
+odown master master 127.0.0.1 16379 #quorum 3/2
  • Sentinal 进行 自动故障切换,协商选定 redis-26329 节点作为新的 主节点
+switch-master master 127.0.0.1 16379 127.0.0.1 26379
  • redis-36329 节点和已经 客观下线 的 redis-16329 节点成为 redis-26479 的 从节点
7954:X 22 Aug 18:48:25.710 * +slave slave 127.0.0.1:36379 127.0.0.1 36379 @ master 127.0.0.1 263797954:X 22 Aug 18:48:25.711 * +slave slave 127.0.0.1:16379 127.0.0.1 16379 @ master 127.0.0.1 26379

6.3. Redis的配置文件

分别查看三个 redis 节点的配置文件,发生 主从切换 时 redis.conf 的配置会自动发生刷新。

  • 节点 redis-16379
daemonize yespidfile "/var/run/redis-16379.pid"logfile "/var/log/redis/redis-16379.log"port 16379bind 0.0.0.0timeout 300databases 16dbfilename "dump-16379.db"dir "/usr/local/redis-sentinel/redis-workdir"masterauth "123456"requirepass "123456" 
  • 节点 redis-26379
daemonize yespidfile "/var/run/redis-26379.pid"logfile "/var/log/redis/redis-26379.log"port 26379bind 0.0.0.0timeout 300databases 16dbfilename "dump-26379.db"dir "/usr/local/redis-sentinel/redis-workdir"masterauth "123456"requirepass "123456"
  • 节点 redis-36379
daemonize yespidfile "/var/run/redis-36379.pid"logfile "/var/log/redis/redis-36379.log"port 36379bind 0.0.0.0timeout 300databases 16dbfilename "dump-36379.db"dir "/usr/local/redis-sentinel/redis-workdir"masterauth "123456"requirepass "123456"slaveof 127.0.0.1 26379

分析:redis-26379 节点 slaveof 配置被移除,晋升为 主节点。redis-16379 节点处于 宕机状态。redis-36379 的 slaveof 配置更新为 127.0.0.1 redis-26379,成为 redis-26379 的 从节点

重启节点 redis-16379。待正常启动后,再次查看它的 redis.conf 文件,配置如下:

daemonize yespidfile "/var/run/redis-16379.pid"logfile "/var/log/redis/redis-16379.log"port 16379bind 0.0.0.0timeout 300databases 16dbfilename "dump-16379.db"dir "/usr/local/redis-sentinel/redis-workdir"masterauth "123456"requirepass "123456"# Generated by CONFIG REWRITEslaveof 127.0.0.1 26379

节点 redis-16379 的配置文件新增一行 slaveof 配置属性,指向 redis-26379,即成为 新的主节点从节点

小结

本文首先对 Redis 实现高可用的几种模式做出了阐述,指出了 Redis 主从复制 的不足之处,进一步引入了 Redis Sentinel 哨兵模式 的相关概念,深入说明了 Redis Sentinel 的 具体功能基本原理高可用搭建自动故障切换 验证等。

当然,Redis Sentinel 仅仅解决了 高可用 的问题,对于 主节点 单点写入和单节点无法扩容等问题,还需要引入 Redis Cluster 集群模式 予以解决。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_34878397/article/details/112226878

智能推荐

使用nginx解决浏览器跨域问题_nginx不停的xhr-程序员宅基地

文章浏览阅读1k次。通过使用ajax方法跨域请求是浏览器所不允许的,浏览器出于安全考虑是禁止的。警告信息如下:不过jQuery对跨域问题也有解决方案,使用jsonp的方式解决,方法如下:$.ajax({ async:false, url: 'http://www.mysite.com/demo.do', // 跨域URL ty..._nginx不停的xhr

在 Oracle 中配置 extproc 以访问 ST_Geometry-程序员宅基地

文章浏览阅读2k次。关于在 Oracle 中配置 extproc 以访问 ST_Geometry,也就是我们所说的 使用空间SQL 的方法,官方文档链接如下。http://desktop.arcgis.com/zh-cn/arcmap/latest/manage-data/gdbs-in-oracle/configure-oracle-extproc.htm其实简单总结一下,主要就分为以下几个步骤。..._extproc

Linux C++ gbk转为utf-8_linux c++ gbk->utf8-程序员宅基地

文章浏览阅读1.5w次。linux下没有上面的两个函数,需要使用函数 mbstowcs和wcstombsmbstowcs将多字节编码转换为宽字节编码wcstombs将宽字节编码转换为多字节编码这两个函数,转换过程中受到系统编码类型的影响,需要通过设置来设定转换前和转换后的编码类型。通过函数setlocale进行系统编码的设置。linux下输入命名locale -a查看系统支持的编码_linux c++ gbk->utf8

IMP-00009: 导出文件异常结束-程序员宅基地

文章浏览阅读750次。今天准备从生产库向测试库进行数据导入,结果在imp导入的时候遇到“ IMP-00009:导出文件异常结束” 错误,google一下,发现可能有如下原因导致imp的数据太大,没有写buffer和commit两个数据库字符集不同从低版本exp的dmp文件,向高版本imp导出的dmp文件出错传输dmp文件时,文件损坏解决办法:imp时指定..._imp-00009导出文件异常结束

python程序员需要深入掌握的技能_Python用数据说明程序员需要掌握的技能-程序员宅基地

文章浏览阅读143次。当下是一个大数据的时代,各个行业都离不开数据的支持。因此,网络爬虫就应运而生。网络爬虫当下最为火热的是Python,Python开发爬虫相对简单,而且功能库相当完善,力压众多开发语言。本次教程我们爬取前程无忧的招聘信息来分析Python程序员需要掌握那些编程技术。首先在谷歌浏览器打开前程无忧的首页,按F12打开浏览器的开发者工具。浏览器开发者工具是用于捕捉网站的请求信息,通过分析请求信息可以了解请..._初级python程序员能力要求

Spring @Service生成bean名称的规则(当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致)_@service beanname-程序员宅基地

文章浏览阅读7.6k次,点赞2次,收藏6次。@Service标注的bean,类名:ABDemoService查看源码后发现,原来是经过一个特殊处理:当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致public class AnnotationBeanNameGenerator implements BeanNameGenerator { private static final String C..._@service beanname

随便推点

二叉树的各种创建方法_二叉树的建立-程序员宅基地

文章浏览阅读6.9w次,点赞73次,收藏463次。1.前序创建#include<stdio.h>#include<string.h>#include<stdlib.h>#include<malloc.h>#include<iostream>#include<stack>#include<queue>using namespace std;typed_二叉树的建立

解决asp.net导出excel时中文文件名乱码_asp.net utf8 导出中文字符乱码-程序员宅基地

文章浏览阅读7.1k次。在Asp.net上使用Excel导出功能,如果文件名出现中文,便会以乱码视之。 解决方法: fileName = HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8);_asp.net utf8 导出中文字符乱码

笔记-编译原理-实验一-词法分析器设计_对pl/0作以下修改扩充。增加单词-程序员宅基地

文章浏览阅读2.1k次,点赞4次,收藏23次。第一次实验 词法分析实验报告设计思想词法分析的主要任务是根据文法的词汇表以及对应约定的编码进行一定的识别,找出文件中所有的合法的单词,并给出一定的信息作为最后的结果,用于后续语法分析程序的使用;本实验针对 PL/0 语言 的文法、词汇表编写一个词法分析程序,对于每个单词根据词汇表输出: (单词种类, 单词的值) 二元对。词汇表:种别编码单词符号助记符0beginb..._对pl/0作以下修改扩充。增加单词

android adb shell 权限,android adb shell权限被拒绝-程序员宅基地

文章浏览阅读773次。我在使用adb.exe时遇到了麻烦.我想使用与bash相同的adb.exe shell提示符,所以我决定更改默认的bash二进制文件(当然二进制文件是交叉编译的,一切都很完美)更改bash二进制文件遵循以下顺序> adb remount> adb push bash / system / bin /> adb shell> cd / system / bin> chm..._adb shell mv 权限

投影仪-相机标定_相机-投影仪标定-程序员宅基地

文章浏览阅读6.8k次,点赞12次,收藏125次。1. 单目相机标定引言相机标定已经研究多年,标定的算法可以分为基于摄影测量的标定和自标定。其中,应用最为广泛的还是张正友标定法。这是一种简单灵活、高鲁棒性、低成本的相机标定算法。仅需要一台相机和一块平面标定板构建相机标定系统,在标定过程中,相机拍摄多个角度下(至少两个角度,推荐10~20个角度)的标定板图像(相机和标定板都可以移动),即可对相机的内外参数进行标定。下面介绍张氏标定法(以下也这么称呼)的原理。原理相机模型和单应矩阵相机标定,就是对相机的内外参数进行计算的过程,从而得到物体到图像的投影_相机-投影仪标定

Wayland架构、渲染、硬件支持-程序员宅基地

文章浏览阅读2.2k次。文章目录Wayland 架构Wayland 渲染Wayland的 硬件支持简 述: 翻译一篇关于和 wayland 有关的技术文章, 其英文标题为Wayland Architecture .Wayland 架构若是想要更好的理解 Wayland 架构及其与 X (X11 or X Window System) 结构;一种很好的方法是将事件从输入设备就开始跟踪, 查看期间所有的屏幕上出现的变化。这就是我们现在对 X 的理解。 内核是从一个输入设备中获取一个事件,并通过 evdev 输入_wayland

推荐文章

热门文章

相关标签