Redis(二)冰叔带你了解Redis-哨兵模式和高可用集群解析
前言
Redis
的 主从复制 模式下,一旦 主节点 由于故障不能提供服务,需要手动将 从节点 晋升为 主节点,同时还要通知 客户端 更新 主节点地址,这种故障处理方式从一定程度上是无法接受的。Redis 2.8
以后提供了 Redis Sentinel
哨兵机制 来解决这个问题。
正文
1. Redis高可用概述
在 Web
服务器中,高可用 是指服务器可以 正常访问 的时间,衡量的标准是在 多长时间 内可以提供正常服务(99.9%
、99.99%
、99.999%
等等)。在 Redis
层面,高可用 的含义要宽泛一些,除了保证提供 正常服务(如 主从分离、快速容灾技术 等),还需要考虑 数据容量扩展、数据安全 等等。
在 Redis
中,实现 高可用 的技术主要包括 持久化、复制、哨兵 和 集群,下面简单说明它们的作用,以及解决了什么样的问题:
持久化:持久化是 最简单的 高可用方法。它的主要作用是 数据备份,即将数据存储在 硬盘,保证数据不会因进程退出而丢失。
复制:复制是高可用
Redis
的基础,哨兵 和 集群 都是在 复制基础 上实现高可用的。复制主要实现了数据的多机备份以及对于读操作的负载均衡和简单的故障恢复。缺陷是故障恢复无法自动化、写操作无法负载均衡、存储能力受到单机的限制。哨兵:在复制的基础上,哨兵实现了 自动化 的 故障恢复。缺陷是 写操作 无法 负载均衡,存储能力 受到 单机 的限制。
集群:通过集群,
Redis
解决了 写操作 无法 负载均衡 以及 存储能力 受到 单机限制 的问题,实现了较为 完善 的 高可用方案。
2. Redis Sentinel的基本概念
Redis Sentinel
是 Redis
高可用 的实现方案。Sentinel
是一个管理多个 Redis
实例的工具,它可以实现对 Redis
的 监控、通知、自动故障转移。下面先对 Redis Sentinel
的 基本概念 进行简单的介绍。
基本名词说明:
基本名词 | 逻辑结构 | 物理结构 |
---|---|---|
Redis数据节点 | 主节点和从节点 | 主节点和从节点的进程 |
主节点(master) | Redis主数据库 | 一个独立的Redis进程 |
从节点(slave) | Redis从数据库 | 一个独立的Redis进程 |
Sentinel节点 | 监控Redis数据节点 | 一个独立的Sentinel进程 |
Sentinel节点集合 | 若干Sentinel节点的抽象组合 | 若干Sentinel节点进程 |
Redis Sentinel | Redis高可用实现方案 | Sentinel节点集合和Redis数据节点进程 |
应用客户端 | 泛指一个或多个客户端 | 一个或者多个客户端进程或者线程 |
如图所示,Redis
的 主从复制模式 和 Sentinel
高可用架构 的示意图:
3. Redis主从复制的问题
Redis
主从复制 可将 主节点 数据同步给 从节点,从节点此时有两个作用:
- 一旦 主节点宕机,从节点 作为 主节点 的 备份 可以随时顶上来。
- 扩展 主节点 的 读能力,分担主节点读压力。
主从复制 同时存在以下几个问题:
一旦 主节点宕机,从节点 晋升成 主节点,同时需要修改 应用方 的 主节点地址,还需要命令所有 从节点 去 复制 新的主节点,整个过程需要 人工干预。
主节点 的 写能力 受到 单机的限制。
主节点 的 存储能力 受到 单机的限制。
原生复制 的弊端在早期的版本中也会比较突出,比如:
Redis
复制中断 后,从节点 会发起psync
。此时如果 同步不成功,则会进行 全量同步,主库 执行 全量备份 的同时,可能会造成毫秒或秒级的 卡顿。
4. Redis Sentinel深入探究
4.1. Redis Sentinel的架构
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
节点询问对该节点的 状态判断。如果超过 <quorum>
个数的节点判定 主节点 不可达,则该 Sentinel
节点会判断 主节点 为 客观下线。
4.4. Sentinel的通信命令
Sentinel
节点连接一个 Redis
实例的时候,会创建 cmd
和 pub/sub
两个 连接。Sentinel
通过 cmd
连接给 Redis
发送命令,通过 pub/sub
连接到 Redis
实例上的其他 Sentinel
实例。
Sentinel
与 Redis
主节点 和 从节点 交互的命令,主要包括:
命令 | 作 用 |
---|---|
PING | Sentinel 向 Redis 节点发送 PING 命令,检查节点的状态 |
INFO | Sentinel 向 Redis 节点发送 INFO 命令,获取它的 从节点信息 |
PUBLISH | Sentinel 向其监控的 Redis 节点 __sentinel__:hello 这个 channel 发布 自己的信息 及 主节点 相关的配置 |
SUBSCRIBE | Sentinel 通过订阅 Redis 主节点 和 从节点 的 __sentinel__:hello 这个 channnel ,获取正在监控相同服务的其他 Sentinel 节点 |
Sentinel
与 Sentinel
交互的命令,主要包括:
命令 | 作 用 |
---|---|
PING | Sentinel 向其他 Sentinel 节点发送 PING 命令,检查节点的状态 |
SENTINEL:is-master-down-by-addr | 和其他 Sentinel 协商 主节点 的状态,如果 主节点 处于 SDOWN 状态,则投票自动选出新的 主节点 |
4.5. Redis Sentinel的工作原理
每个 Sentinel
节点都需要 定期执行 以下任务:
- 每个
Sentinel
以 每秒钟 一次的频率,向它所知的 主服务器、从服务器 以及其他Sentinel
实例 发送一个PING
命令。
- 如果一个 实例(
instance
)距离 最后一次 有效回复PING
命令的时间超过down-after-milliseconds
所指定的值,那么这个实例会被Sentinel
标记为 主观下线。
- 如果一个 主服务器 被标记为 主观下线,那么正在 监视 这个 主服务器 的所有
Sentinel
节点,要以 每秒一次 的频率确认 主服务器 的确进入了 主观下线 状态。
- 如果一个 主服务器 被标记为 主观下线,并且有 足够数量 的
Sentinel
(至少要达到 配置文件 指定的数量)在指定的 时间范围 内同意这一判断,那么这个 主服务器 被标记为 客观下线。
- 在一般情况下, 每个
Sentinel
会以每10
秒一次的频率,向它已知的所有 主服务器 和 从服务器 发送INFO
命令。当一个 主服务器 被Sentinel
标记为 客观下线 时,Sentinel
向 下线主服务器 的所有 从服务器 发送INFO
命令的频率,会从10
秒一次改为 每秒一次。
Sentinel
和其他Sentinel
协商 主节点 的状态,如果 主节点 处于SDOWN
状态,则投票自动选出新的 主节点。将剩余的 从节点 指向 新的主节点 进行 数据复制。
- 当没有足够数量的
Sentinel
同意 主服务器 下线时, 主服务器 的 客观下线状态 就会被移除。当 主服务器 重新向Sentinel
的PING
命令返回 有效回复 时,主服务器 的 主观下线状态 就会被移除。
注意:一个有效的
PING
回复可以是:+PONG
、-LOADING
或者-MASTERDOWN
。如果 服务器 返回除以上三种回复之外的其他回复,又或者在 指定时间 内没有回复PING
命令, 那么Sentinel
认为服务器返回的回复 无效(non-valid
)。
5. Redis Sentinel搭建
5.1. Redis Sentinel的部署须知
一个稳健的
Redis Sentinel
集群,应该使用至少 三个Sentinel
实例,并且保证讲这些实例放到 不同的机器 上,甚至不同的 物理区域。Sentinel
无法保证 强一致性。常见的 客户端应用库 都支持
Sentinel
。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 <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 127.0.0.1 6379 2 # 当在Redis实例中开启了requirepass <foobared>,所有连接Redis实例的客户端都要提供密码。
# sentinel auth-pass <master-name> <password>
sentinel auth-pass mymaster 123456 # 指定主节点应答哨兵sentinel的最大时间间隔,超过这个时间,哨兵主观上认为主节点下线,默认30秒
# sentinel down-after-milliseconds <master-name> <milliseconds>
sentinel down-after-milliseconds mymaster 30000 # 指定了在发生failover主备切换时,最多可以有多少个slave同时对新的master进行同步。这个数字越小,完成failover所需的时间就越长;反之,但是如果这个数字越大,就意味着越多的slave因为replication而不可用。可以通过将这个值设为1,来保证每次只有一个slave,处于不能处理命令请求的状态。
# sentinel parallel-syncs <master-name> <numslaves>
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 <master-name> <milliseconds>
sentinel failover-timeout mymaster 180000 # 当sentinel有任何警告级别的事件发生时(比如说redis实例的主观失效和客观失效等等),将会去调用这个脚本。一个脚本的最大执行时间为60s,如果超过这个时间,脚本将会被一个SIGKILL信号终止,之后重新执行。
# 对于脚本的运行结果有以下规则:
## 1. 若脚本执行后返回1,那么该脚本稍后将会被再次执行,重复次数目前默认为10。
## 2. 若脚本执行后返回2,或者比2更高的一个返回值,脚本将不会重复执行。
## 3. 如果脚本在执行过程中由于收到系统中断信号被终止了,则同返回值为1时的行为相同。
# sentinel notification-script <master-name> <script-path>
sentinel notification-script mymaster /var/redis/notify.sh # 这个脚本应该是通用的,能被多次调用,不是针对性的。
# sentinel client-reconfig-script <master-name> <script-path>
sentinel client-reconfig-script mymaster /var/redis/reconfig.sh
5.3. Redis Sentinel的节点规划
角色 | IP地址 | 端口号 |
---|---|---|
Redis Master | 10.206.20.231 | 16379 |
Redis Slave1 | 10.206.20.231 | 26379 |
Redis Slave2 | 10.206.20.231 | 36379 |
Redis Sentinel1 | 10.206.20.231 | 16380 |
Redis Sentinel2 | 10.206.20.231 | 26380 |
Redis Sentinel3 | 10.206.20.231 | 36380 |
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 yes
pidfile /var/run/redis-16379.pid
logfile /var/log/redis/redis-16379.log
port 16379
bind 0.0.0.0
timeout 300
databases 16
dbfilename dump-16379.db
dir ./redis-workdir
masterauth 123456
requirepass 123456
- 从节点1:redis-26379.conf
daemonize yes
pidfile /var/run/redis-.pid
logfile /var/log/redis/redis-.log
port
bind 0.0.0.0
timeout
databases
dbfilename dump-.db
dir ./redis-workdir
masterauth
requirepass
slaveof 127.0.0.1
- 从节点2:redis-36379.conf
daemonize yes
pidfile /var/run/redis-.pid
logfile /var/log/redis/redis-.log
port
bind 0.0.0.0
timeout
databases
dbfilename dump-.db
dir ./redis-workdir
masterauth
requirepass
slaveof 127.0.0.1
如果要做 自动故障转移,建议所有的
redis.conf
都设置masterauth
。因为 自动故障 只会重写 主从关系,即slaveof
,不会自动写入masterauth
。如果Redis
原本没有设置密码,则可以忽略。
5.4.2. Redis-Server启动验证
按顺序分别启动 16379
,26379
和 36379
三个 Redis
节点,启动命令和启动日志如下:
Redis
的启动命令:
$ sudo redis-server /usr/local/redis-sentinel/redis-.conf
$ sudo redis-server /usr/local/redis-sentinel/redis-.conf
$ sudo redis-server /usr/local/redis-sentinel/redis-.conf
查看 Redis
的启动进程:
$ ps -ef | grep redis-server
:16下午 ?? :01.84 redis-server 0.0.0.0:
:16下午 ?? :01.73 redis-server 0.0.0.0:
:16下午 ?? :01.70 redis-server 0.0.0.0:
查看 Redis
的启动日志:
- 节点
redis-16379
$ cat /var/log/redis/redis-.log
:C Aug ::38.907 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
:C Aug ::38.908 # Redis version=4.0., bits=, commit=, modified=, pid=, just started
:C Aug ::38.908 # Configuration loaded
:M Aug ::38.910 * Increased maximum number of open files to (it was originally set to ).
:M Aug ::38.912 * Running mode=standalone, port=.
:M Aug ::38.913 # Server initialized
:M Aug ::38.913 * Ready to accept connections
:M Aug ::48.416 * Slave 127.0.0.1: asks for synchronization
:M Aug ::48.416 * Full resync requested by slave 127.0.0.1:
:M Aug ::48.416 * Starting BGSAVE for SYNC with target: disk
:M Aug ::48.416 * Background saving started by pid
:C Aug ::48.433 * DB saved on disk
:M Aug ::48.487 * Background saving terminated with success
:M Aug ::48.494 * Synchronization with slave 127.0.0.1: succeeded
:M Aug ::51.848 * Slave 127.0.0.1: asks for synchronization
:M Aug ::51.849 * Full resync requested by slave 127.0.0.1:
:M Aug ::51.849 * Starting BGSAVE for SYNC with target: disk
:M Aug ::51.850 * Background saving started by pid
:C Aug ::51.862 * DB saved on disk
:M Aug ::51.919 * Background saving terminated with success
:M Aug ::51.923 * Synchronization with slave 127.0.0.1: succeeded
以下两行日志日志表明,redis-16379
作为 Redis
的 主节点,redis-26379
和 redis-36379
作为 从节点,从 主节点 同步数据。
:M Aug ::48.416 * Slave 127.0.0.1: asks for synchronization
:M Aug ::51.848 * Slave 127.0.0.1: asks for synchronization
- 节点
redis-26379
$ cat /var/log/redis/redis-.log
:C Aug ::48.407 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
:C Aug ::48.408 # Redis version=4.0., bits=, commit=, modified=, pid=, just started
:C Aug ::48.408 # Configuration loaded
:S Aug ::48.410 * Increased maximum number of open files to (it was originally set to ).
:S Aug ::48.412 * Running mode=standalone, port=.
:S Aug ::48.413 # Server initialized
:S Aug ::48.413 * Ready to accept connections
:S Aug ::48.413 * Connecting to MASTER 127.0.0.1:
:S Aug ::48.413 * MASTER <-> SLAVE sync started
:S Aug ::48.414 * Non blocking connect for SYNC fired the event.
:S Aug ::48.414 * Master replied to PING, replication can continue...
:S Aug ::48.415 * Partial resynchronization not possible (no cached master)
:S Aug ::48.417 * Full resync from master: 211d3b4eceaa3af4fe5c77d22adf06e1218e0e7b:
:S Aug ::48.494 * MASTER <-> SLAVE sync: receiving bytes from master
:S Aug ::48.495 * MASTER <-> SLAVE sync: Flushing old data
:S Aug ::48.496 * MASTER <-> SLAVE sync: Loading DB in memory
:S Aug ::48.498 * MASTER <-> SLAVE sync: Finished with success
- 节点
redis-36379
$ cat /var/log/redis/redis-.log
:C Aug ::51.839 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
:C Aug ::51.840 # Redis version=4.0., bits=, commit=, modified=, pid=, just started
:C Aug ::51.841 # Configuration loaded
:S Aug ::51.843 * Increased maximum number of open files to (it was originally set to ).
:S Aug ::51.845 * Running mode=standalone, port=.
:S Aug ::51.845 # Server initialized
:S Aug ::51.846 * Ready to accept connections
:S Aug ::51.846 * Connecting to MASTER 127.0.0.1:
:S Aug ::51.847 * MASTER <-> SLAVE sync started
:S Aug ::51.847 * Non blocking connect for SYNC fired the event.
:S Aug ::51.847 * Master replied to PING, replication can continue...
:S Aug ::51.848 * Partial resynchronization not possible (no cached master)
:S Aug ::51.850 * Full resync from master: 211d3b4eceaa3af4fe5c77d22adf06e1218e0e7b:
:S Aug ::51.923 * MASTER <-> SLAVE sync: receiving bytes from master
:S Aug ::51.923 * MASTER <-> SLAVE sync: Flushing old data
:S Aug ::51.924 * MASTER <-> SLAVE sync: Loading DB in memory
:S Aug ::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./sentinel.conf /usr/local/redis-sentinel/sentinel-.conf
$ sudo cp /usr/local/redis-4.0./sentinel.conf /usr/local/redis-sentinel/sentinel-.conf
$ sudo cp /usr/local/redis-4.0./sentinel.conf /usr/local/redis-sentinel/sentinel-.conf
- 节点1:sentinel-16380.conf
protected-mode no
bind 0.0.0.0
port
daemonize yes
sentinel monitor master 127.0.0.1
sentinel down-after-milliseconds master
sentinel failover-timeout master
sentinel parallel-syncs master
sentinel auth-pass master
logfile /var/log/redis/sentinel-.log
- 节点2:sentinel-26380.conf
protected-mode no
bind 0.0.0.0
port
daemonize yes
sentinel monitor master 127.0.0.1
sentinel down-after-milliseconds master
sentinel failover-timeout master
sentinel parallel-syncs master
sentinel auth-pass master
logfile /var/log/redis/sentinel-.log
- 节点3:sentinel-36380.conf
protected-mode no
bind 0.0.0.0
port
daemonize yes
sentinel monitor master 127.0.0.1
sentinel down-after-milliseconds master
sentinel failover-timeout master
sentinel parallel-syncs master
sentinel auth-pass master
logfile /var/log/redis/sentinel-.log
5.4.4. Sentinel启动验证
按顺序分别启动 16380
,26380
和 36380
三个 Sentinel
节点,启动命令和启动日志如下:
$ sudo redis-sentinel /usr/local/redis-sentinel/sentinel-.conf
$ sudo redis-sentinel /usr/local/redis-sentinel/sentinel-.conf
$ sudo redis-sentinel /usr/local/redis-sentinel/sentinel-.conf
查看 Sentinel
的启动进程:
$ ps -ef | grep redis-sentinel
:30下午 ?? :00.05 redis-sentinel 0.0.0.0: [sentinel]
:30下午 ?? :00.05 redis-sentinel 0.0.0.0: [sentinel]
:30下午 ?? :00.04 redis-sentinel 0.0.0.0: [sentinel]
查看 Sentinel
的启动日志:
- 节点
sentinel-16380
$ cat /var/log/redis/sentinel-.log
:X Aug ::27.245 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
:X Aug ::27.245 # Redis version=4.0., bits=, commit=, modified=, pid=, just started
:X Aug ::27.245 # Configuration loaded
:X Aug ::27.247 * Increased maximum number of open files to (it was originally set to ).
:X Aug ::27.249 * Running mode=sentinel, port=.
:X Aug ::27.250 # Sentinel ID is 69d05b86a82102a8919231fd3c2d1f21ce86e000
:X Aug ::27.250 # +monitor master master 127.0.0.1 quorum
:X Aug ::32.286 # +sdown sentinel fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7 127.0.0.1 @ master 127.0.0.1
:X Aug ::34.588 # -sdown sentinel fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7 127.0.0.1 @ master 127.0.0.1
sentinel-16380
节点的 Sentinel ID
为 69d05b86a82102a8919231fd3c2d1f21ce86e000
,并通过 Sentinel ID
把自身加入 sentinel
集群中。
- 节点
sentinel-26380
$ cat /var/log/redis/sentinel-.log
:X Aug ::30.900 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
:X Aug ::30.901 # Redis version=4.0., bits=, commit=, modified=, pid=, just started
:X Aug ::30.901 # Configuration loaded
:X Aug ::30.904 * Increased maximum number of open files to (it was originally set to ).
:X Aug ::30.905 * Running mode=sentinel, port=.
:X Aug ::30.906 # Sentinel ID is 21e30244cda6a3d3f55200bcd904d0877574e506
:X Aug ::30.906 # +monitor master master 127.0.0.1 quorum
:X Aug ::30.907 * +slave slave 127.0.0.1: 127.0.0.1 @ master 127.0.0.1
:X Aug ::30.911 * +slave slave 127.0.0.1: 127.0.0.1 @ master 127.0.0.1
:X Aug ::36.311 * +sentinel sentinel fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7 127.0.0.1 @ master 127.0.0.1
sentinel-26380
节点的 Sentinel ID
为 21e30244cda6a3d3f55200bcd904d0877574e506
,并通过 Sentinel ID
把自身加入 sentinel
集群中。此时 sentinel
集群中已有 sentinel-16380
和 sentinel-26380
两个节点。
- 节点
sentinel-36380
$ cat /var/log/redis/sentinel-.log
:X Aug ::34.273 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
:X Aug ::34.274 # Redis version=4.0., bits=, commit=, modified=, pid=, just started
:X Aug ::34.274 # Configuration loaded
:X Aug ::34.276 * Increased maximum number of open files to (it was originally set to ).
:X Aug ::34.277 * Running mode=sentinel, port=.
:X Aug ::34.278 # Sentinel ID is fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7
:X Aug ::34.278 # +monitor master master 127.0.0.1 quorum
:X Aug ::34.279 * +slave slave 127.0.0.1: 127.0.0.1 @ master 127.0.0.1
:X Aug ::34.283 * +slave slave 127.0.0.1: 127.0.0.1 @ master 127.0.0.1
:X Aug ::34.993 * +sentinel sentinel 21e30244cda6a3d3f55200bcd904d0877574e506 127.0.0.1 @ master 127.0.0.1
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 REWRITE
dir "/usr/local/redis-sentinel"
sentinel config-epoch master
sentinel leader-epoch master
sentinel known-slave master 127.0.0.1
sentinel known-slave master 127.0.0.1
sentinel known-sentinel master 127.0.0.1 21e30244cda6a3d3f55200bcd904d0877574e506
sentinel known-sentinel master 127.0.0.1 fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7
sentinel current-epoch
可以注意到,sentinel-16380.conf
刷新写入了 Redis
主节点关联的所有 从节点 redis-26379
和 redis-36379
,同时写入了其余两个 Sentinel
节点 sentinel-26380
和 sentinel-36380
的 IP
地址,端口号 和 Sentinel ID
。
# Generated by CONFIG REWRITE
dir "/usr/local/redis-sentinel"
sentinel config-epoch master
sentinel leader-epoch master
sentinel known-slave master 127.0.0.1
sentinel known-slave master 127.0.0.1
sentinel known-sentinel master 127.0.0.1 fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7
sentinel known-sentinel master 127.0.0.1 69d05b86a82102a8919231fd3c2d1f21ce86e000
sentinel current-epoch
可以注意到,sentinel-26380.conf
刷新写入了 Redis
主节点关联的所有 从节点 redis-26379
和 redis-36379
,同时写入了其余两个 Sentinel
节点 sentinel-36380
和 sentinel-16380
的 IP
地址,端口号 和 Sentinel ID
。
# Generated by CONFIG REWRITE
dir "/usr/local/redis-sentinel"
sentinel config-epoch master
sentinel leader-epoch master
sentinel known-slave master 127.0.0.1
sentinel known-slave master 127.0.0.1
sentinel known-sentinel master 127.0.0.1 69d05b86a82102a8919231fd3c2d1f21ce86e000
sentinel known-sentinel master 127.0.0.1 21e30244cda6a3d3f55200bcd904d0877574e506
sentinel current-epoch
可以注意到,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 <master_name>
- 显示指定 主节点 的所有 从节点 以及它们的状态。
> SENTINEL slaves <master_name>
返回指定 主节点 的 IP
地址和 端口。如果正在进行 failover
或者 failover
已经完成,将会显示被提升为 主节点 的 从节点 的 IP
地址和 端口。
> SENTINEL get-master-addr-by-name <master_name>
- 重置名字匹配该 正则表达式 的所有的 主节点 的状态信息,清除它之前的 状态信息,以及 从节点 的信息。
> SENTINEL reset <pattern>
- 强制当前
Sentinel
节点执行failover
,并且不需要得到其他Sentinel
节点的同意。但是failover
后会将 最新的配置 发送给其他Sentinel
节点。
>SENTINEL failover <master_name>
6. Redis Sentinel故障切换与恢复
6.1. Redis CLI客户端跟踪
上面的日志显示,redis-16379
节点为 主节点,它的进程 ID
为 7127
。为了模拟 Redis
主节点故障,强制杀掉这个进程。
$ kill -
使用 redis-cli
客户端命令进入 sentinel-16380
节点,查看 Redis
节点 的状态信息。
$ redis-cli -p
- 查看
Redis
主从集群的 主节点 信息。可以发现redis-26379
晋升为 新的主节点。
127.0.0.1:> SENTINEL master master
) "name"
) "master"
) "ip"
) "127.0.0.1"
) "port"
) ""
) "runid"
) "b8ca3b468a95d1be5efe1f50c50636cafe48c59f"
) "flags"
) "master"
) "link-pending-commands"
) ""
) "link-refcount"
) ""
) "last-ping-sent"
) ""
) "last-ok-ping-reply"
) ""
) "last-ping-reply"
) ""
) "down-after-milliseconds"
) ""
) "info-refresh"
) ""
) "role-reported"
) "master"
) "role-reported-time"
) ""
) "config-epoch"
) ""
) "num-slaves"
) ""
) "num-other-sentinels"
) ""
) "quorum"
) ""
) "failover-timeout"
) ""
) "parallel-syncs"
) ""
6.2. Redis Sentinel日志跟踪
查看任意 Sentinel
节点的日志如下:
:X Aug ::22.504 # +tilt #tilt mode entered
:X Aug ::32.197 # +tilt #tilt mode entered
:X Aug ::02.241 # -tilt #tilt mode exited
:X Aug ::24.550 # +sdown master master 127.0.0.1
:X Aug ::24.647 # +new-epoch
:X Aug ::24.651 # +vote-for-leader fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7
:X Aug ::25.678 # +odown master master 127.0.0.1 #quorum /
:X Aug ::25.678 # Next failover delay: I will not start a failover before Wed Aug ::
:X Aug ::25.709 # +config-update-from sentinel fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7 127.0.0.1 @ master 127.0.0.1
:X Aug ::25.710 # +switch-master master 127.0.0.1 127.0.0.1
:X Aug ::25.710 * +slave slave 127.0.0.1: 127.0.0.1 @ master 127.0.0.1
:X Aug ::25.711 * +slave slave 127.0.0.1: 127.0.0.1 @ master 127.0.0.1
:X Aug ::30.738 # +sdown slave 127.0.0.1: 127.0.0.1 @ master 127.0.0.1
:X Aug ::23.479 # -sdown slave 127.0.0.1: 127.0.0.1 @ master 127.0.0.1
- 分析日志,可以发现
redis-16329
节点先进入sdown
主观下线 状态。
+sdown master master 127.0.0.1
- 哨兵检测到
redis-16329
出现故障,Sentinel
进入一个 新纪元,从0
变为1
。
+new-epoch
- 三个
Sentinel
节点开始协商 主节点 的状态,判断其是否需要 客观下线。
+vote-for-leader fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7
- 超过
quorum
个数的Sentinel
节点认为 主节点 出现故障,redis-16329
节点进入 客观下线 状态。
+odown master master 127.0.0.1 #quorum /
Sentinal
进行 自动故障切换,协商选定redis-26329
节点作为新的 主节点。
+switch-master master 127.0.0.1 127.0.0.1
redis-36329
节点和已经 客观下线 的redis-16329
节点成为redis-26479
的 从节点。
:X Aug ::25.710 * +slave slave 127.0.0.1: 127.0.0.1 @ master 127.0.0.1
:X Aug ::25.711 * +slave slave 127.0.0.1: 127.0.0.1 @ master 127.0.0.1
6.3. Redis的配置文件
分别查看三个 redis
节点的配置文件,发生 主从切换 时 redis.conf
的配置会自动发生刷新。
- 节点 redis-16379
daemonize yes
pidfile "/var/run/redis-16379.pid"
logfile "/var/log/redis/redis-16379.log"
port
bind 0.0.0.0
timeout
databases
dbfilename "dump-16379.db"
dir "/usr/local/redis-sentinel/redis-workdir"
masterauth ""
requirepass ""
- 节点 redis-26379
daemonize yes
pidfile "/var/run/redis-26379.pid"
logfile "/var/log/redis/redis-26379.log"
port
bind 0.0.0.0
timeout
databases
dbfilename "dump-26379.db"
dir "/usr/local/redis-sentinel/redis-workdir"
masterauth ""
requirepass ""
- 节点 redis-36379
daemonize yes
pidfile "/var/run/redis-36379.pid"
logfile "/var/log/redis/redis-36379.log"
port
bind 0.0.0.0
timeout
databases
dbfilename "dump-36379.db"
dir "/usr/local/redis-sentinel/redis-workdir"
masterauth ""
requirepass ""
slaveof 127.0.0.1
分析:
redis-26379
节点slaveof
配置被移除,晋升为 主节点。redis-16379
节点处于 宕机状态。redis-36379
的slaveof
配置更新为127.0.0.1 redis-26379
,成为redis-26379
的 从节点。
重启节点 redis-16379
。待正常启动后,再次查看它的 redis.conf
文件,配置如下:
daemonize yes
pidfile "/var/run/redis-16379.pid"
logfile "/var/log/redis/redis-16379.log"
port
bind 0.0.0.0
timeout
databases
dbfilename "dump-16379.db"
dir "/usr/local/redis-sentinel/redis-workdir"
masterauth ""
requirepass ""
# Generated by CONFIG REWRITE
slaveof 127.0.0.1
节点 redis-16379
的配置文件新增一行 slaveof
配置属性,指向 redis-26379
,即成为 新的主节点 的 从节点。
小结
本文首先对 Redis
实现高可用的几种模式做出了阐述,指出了 Redis
主从复制 的不足之处,进一步引入了 Redis Sentinel
哨兵模式 的相关概念,深入说明了 Redis Sentinel
的 具体功能,基本原理,高可用搭建 和 自动故障切换 验证等。
当然,Redis Sentinel
仅仅解决了 高可用 的问题,对于 主节点 单点写入和单节点无法扩容等问题,还需要引入 Redis Cluster
集群模式 予以解决。
欢迎大家技术交流微信hsj179540
Redis(二)冰叔带你了解Redis-哨兵模式和高可用集群解析的更多相关文章
- Redis总结(五)缓存雪崩和缓存穿透等问题 Web API系列(三)统一异常处理 C#总结(一)AutoResetEvent的使用介绍(用AutoResetEvent实现同步) C#总结(二)事件Event 介绍总结 C#总结(三)DataGridView增加全选列 Web API系列(二)接口安全和参数校验 RabbitMQ学习系列(六): RabbitMQ 高可用集群
Redis总结(五)缓存雪崩和缓存穿透等问题 前面讲过一些redis 缓存的使用和数据持久化.感兴趣的朋友可以看看之前的文章,http://www.cnblogs.com/zhangweizhon ...
- Redis系列(二):Redis高可用集群
一.集群模式 Redis集群是一个由多个主从节点组成的高可用集群,它具有复制.高可用和分片等特性 二.集群部署 1.环境 3台主机分别是: 192.168.160.146 192.168.160.15 ...
- sentinel监控redis高可用集群(一)
一.首先配置redis的主从同步集群. 1.主库的配置文件不用修改,从库的配置文件只需增加一行,说明主库的IP端口.如果需要验证的,也要加多一行,认证密码. slaveof 192.168.20.26 ...
- Redis Cluster高可用集群在线迁移操作记录【转】
之前介绍了redis cluster的结构及高可用集群部署过程,今天这里简单说下redis集群的迁移.由于之前的redis cluster集群环境部署的服务器性能有限,需要迁移到高配置的服务器上.考虑 ...
- Redis Cluster 4.0高可用集群安装、在线迁移操作记录
之前介绍了redis cluster的结构及高可用集群部署过程,今天这里简单说下redis集群的迁移.由于之前的redis cluster集群环境部署的服务器性能有限,需要迁移到高配置的服务器上.考虑 ...
- Redis Cluster高可用集群在线迁移操作记录
之前介绍了redis cluster的结构及高可用集群部署过程,今天这里简单说下redis集群的迁移.由于之前的redis cluster集群环境部署的服务器性能有限,需要迁移到高配置的服务器上.考虑 ...
- Redis高可用集群-哨兵模式(Redis-Sentinel)搭建配置教程【Windows环境】
No cross,no crown . 不经历风雨,怎么见彩虹. Redis哨兵模式,用现在流行的话可以说就是一个"哨兵机器人",给"哨兵机器人"进行相应的配置 ...
- Redis创建高可用集群教程【Windows环境】
模仿的过程中,加入自己的思考和理解,也会有进步和收获. 在这个互联网时代,在高并发和高流量可能随时爆发的情况下,单机版的系统或者单机版的应用已经无法生存,越来越多的应用开始支持集群,支持分布式部署了. ...
- Redis安装、主从配置及两种高可用集群搭建
Redis安装.主从配置及两种高可用集群搭建 一. 准备 Kali Linux虚拟机 三台:192.168.154.129.192.168.154.130.192.168.154 ...
随机推荐
- js 单项链表
介绍链表 链表是由一组节点组成的集合.每一个节点都使用一个对象的引用指向它的后续借点.指向另外一个借点的引用叫做链. 很多编程语言中数组的长度是固定的,就是定义数组的时候需要定义数组的长度,所以当数组 ...
- Bootstrap图像
前面的话 图像在网页制作中也是常要用到的元素,本文将详细介绍Bootstrap图像 响应式图片 通过为图片添加 .img-responsive 类可以让图片支持响应式布局.其实质是为图片设置了 max ...
- 16mysql1
一.数据库的基本概念 1.1 常用的关系型数据库 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库. 1.2 sql语言 ...
- BZOJ4943 NOI2017蚯蚓排队(哈希+链表)
能看懂题就能想到正解.维护所有长度不超过k的数字串的哈希值即可,用链表维护一下蚯蚓间连接情况.由于这样的数字串至多只有nk个,计算哈希值的总复杂度为O(nk),而分裂的复杂度为O(ck^2),询问复杂 ...
- Mercurial(Hg)基本操作
Mercurial(Hg)基本操作 来源 https://www.cnblogs.com/gb2013/archive/2012/05/18/Mercurial_Basic.html Mercuria ...
- 自学Linux Shell5.2-shell内建命令history alias
点击返回 自学Linux命令行与Shell脚本之路 5.2-shell内建命令history alias 外部命令:有时称为文件系统命令,是存在于bash shell之外的程序,通常位于/bin./u ...
- BZOJ 3526: [Poi2014]Card
3526: [Poi2014]Card Time Limit: 25 Sec Memory Limit: 64 MBSubmit: 267 Solved: 191[Submit][Status][ ...
- HGOI 20190218 题解
/* 又是AK局... hjc又双叒叕AK了... Hmmm...我侥幸 */ Problem A card 给出无序序列a[]可以选择一个数插入到合适的位置作为一次操作,至少多少次操作后可以把序列变 ...
- luogu1072 [NOIp2009]Hankson的趣味题 (数学+STL::set)
一个JSB做法 由$\frac{x*b0}{gcd(x,b0)}=b1$,可得$\frac{x}{gcd(x,b0)}=\frac{b1}{b0}$ 设$b2=\frac{b1}{b0}$ 所以对$b ...
- Linux下定时器
http://unix8.net/linux%E4%B8%8B%E5%AE%9A%E6%97%B6%E5%99%A8.html 一. 基础知识 1.时间类型.Linux下常用的时间类型有4个:time ...