Redis高可用
高可用性(High Availability,HA)主要是为了确保系统在面对故障、负载变化等情况下仍能持续提供服务。
HA场景下,主要是解决这些问题。
问题 | 问题描述 | 解决方案 |
---|---|---|
单点故障 | 如果只有一个 Redis 实例,当它发生故障时,整个系统将无法访问缓存数据,导致服务中断。 | 通过主从复制和哨兵机制,确保在主节点故障时可以快速切换到从节点,保持服务可用性。 |
数据丢失 | 在节点故障或系统崩溃时,数据可能会丢失,导致系统无法恢复到最新状态。 | 通过主从复制和持久化机制(如 RDB 和 AOF),保证数据在多个节点上有副本,降低数据丢失的风险。 |
负载均衡 | 单个 Redis 实例的性能有限,在高并发访问时可能成为瓶颈。 | 通过主从复制实现读写分离,从节点分担读负载;通过集群机制将数据分片到多个节点上,分散负载。 |
自动故障恢复 | 当节点故障时,如果需要人工介入进行恢复,将增加系统停机时间。 | 通过哨兵机制实现自动故障检测和转移,减少人工干预,快速恢复服务。 |
扩展性 | 随着数据量和访问量的增长,单个节点无法满足需求,需要增加更多的节点来扩展系统容量和性能。 | 通过集群机制,支持横向扩展,可以动态添加或移除节点,适应业务增长需求。 |
Redis中,针对高可用场景,主要有以下3个模式。
机制 | 描述 | 优点 | 缺点 | 适用场景 |
---|---|---|---|---|
主从复制 | 数据从主节点复制到一个或多个从节点 | 读写分离,提高性能 数据冗余,提高可用性和安全性 |
单点故障,需要手动故障转移。 | 需要读写分离,提高读性能的场景 |
哨兵 (Sentinel) | 监控 Redis 实例,自动进行故障转移 | 自动化故障检测和转移 扩展性强,管理多个实例 |
配置复杂 网络分区可能导致脑裂问题 |
需要高可用性和自动故障转移的场景 |
集群 (Cluster) | 数据自动分片和复制,支持分布式存储 | 高可用性,通过主从复制和自动故障转移 高扩展性,支持横向扩展 |
配置和管理复杂 对网络要求高 |
大规模分布式存储需求,需高可用和扩展性 |
然后,注意下redis服务的启动方式,免得你看到后文配置时范懵。
咱们的redis-server
,如果有配置文件,会从配置文件中读取值,同时,也支持启动的时候命令中传入参数。
同时存在的时候,命令行参数优先。比如配置文件里和命令行都声明了port,以命令行的为准。
正常情况下,我们直接跟上配置文件地址就行了。
redis-server /path/to/redis.conf
想要额外参数,也可以自己传入。
redis-server /path/to/redis.conf --port 6380
最后,不要纠结配置文件的名字。
记得我最开始学代码的时候,经常看到说,某某组件的必须要声明一个xx的配置文件。
其实,必须要xx名字,只是因为那个组件规定了些默认名字来读取。
redis这里没有这么复杂,我们只要能传进去合法的配置文件,redis就能正常启动。
redis-server /path/to/master.conf
redis-server /path/to/slave.conf
我们可以推测,redis这里是怎么处理的。
- 参数是个list,找到
.conf
结尾的,认为是个配置文件,将其进行加载。 - 其余参数,覆盖配置文件中的参数。
那我传了两个conf进去呢?简单的方式就是直接忽略掉后面的,那我不忽略也可以,我覆盖前面重复的项。
每个人代码风格不一样,对读取配置时的思路不一样,仅此而已。
我特意写这么一点,是怕误导你,也是救赎下曾经的自己,陷在各种奇怪的问题上。
怕你以为,主从啊,它的从节点配置文件名必须是slave.conf,没有这个规定,slave666.conf也没问题。
1.1 主从复制
主从复制是 Redis 高可用性的基础,通过复制机制,数据可以从主节点(Master)复制到一个或多个从节点(Slave)。
当主节点发生故障时,从节点可以作为备份数据源,并且可以提升为新的主节点。
1.1.1 实现
首先,显然生产环境是不能单机跑的,宕机了就GG,那么必然是需要2个以上的Redis做冗余的,最简单的方式,就是两个机器同时跑。
同时跑的时候,存在几个基本问题。
- 数据一致性:只在主节点写数据,然后从节点只同步数据,这样数据就不会混乱。
- 单点故障:手动重新选取一个节点当master
主从模式的运行图示如下,注意图中的主(master)从(slave)节点。
- 主节点(master):读/写
- 从节点(replica):只读
1.1.2 配置
下方演示一个1主1的配置。
类型 | 端口 | 说明 |
---|---|---|
master | 6379 | redis主节点 |
slave | 6380 | redis从节点 |
1. 配置主节点
主节点不需要特殊的配置,只需启动一个 Redis 实例即可。
# 配置文件为/etc/redis/redis.conf
# 启动主节点
redis-server /etc/redis/redis.conf
2. 配置从节点
2.1 配置文件
从节点需要配置对应的主节点。
编辑从节点的配置文件 redis.conf
,添加以下配置,基本配置如下。
# 从节点配置目标主节点
replicaof 192.168.1.100 6379
# 如果主节点设置了密码,还需要在从节点配置文件中添加以下配置
masterauth password
启动从节点
redis-server /path/to/your/slave-redis.conf
2.2 命令方式
命令行是一次性的喔,重启就失效了,只是列一下。
连接到从节点
redis-cli -h <slave-ip> -p <slave-port>
在 Redis CLI 中执行以下命令配置从节点:
SLAVEOF 192.168.1.100 6379
CONFIG SET masterauth your-master-password
3.验证主从复制配置
连接到主节点和从节点,分别执行以下命令验证配置。
3.1 主节点
INFO replication
输出类似以下内容,表明主节点配置正确:
# Replication
# 角色为master
role:master
connected_slaves:1
slave0:ip=<slave-ip>,port=<slave-port>,state=online,offset=12345,lag=0
3.2 从节点
INFO replication
输出类似以下内容,表明从节点配置正确:
# Replication
# 角色为slave
role:slave
master_host:192.168.1.100
master_port:6379
# 主节点状态up
master_link_status:up
3.3 直接查看
或者直接传入命令查看
# 6379 主节点
redis-cli -p 6379 -a 密码 info replication
# 6380 从节点
redis-cli -p 6380 -a 密码 info replication
4. 其他配置选项
可以根据需求配置一些高级选项,例如复制延迟、心跳间隔等:
repl-diskless-sync no # 是否使用无盘复制
repl-diskless-sync-delay 5 # 无盘复制延迟
repl-ping-slave-period 10 # 从节点向主节点发送 PING 命令的间隔
repl-timeout 60 # 复制超时时间
1.1.3 扩展
1.主从模式的数据同步方式
1.1 全量数据同步-SYNC
Redis 在 2.8 版本之前都是基于 SYNC 命令执行全量同步。
SYNC
命令的格式非常简单,没有参数,直接发送 SYNC
即可。
SYNC
简单来说,就是:
- slave加入后,找mater节点要RDB文件。
- master节点构建RDB文件(构建期间新增的数据,写在复制缓冲区中)
- slave收到RDB文件,重建缓存信息。
- master节点将复制缓冲区的数据同步给slave节点。
- 配置完成后,master和slave之间会保持持续的连接和同步,主节点的写命令会实时传送到从节点。
现在有个问题,master节点在收到从节点的同步请求后,会构建rdb文件,这个构建期间的命令怎么办?
master 为每一个 slave 单独开辟一块replication buffer
(复制缓存区)来记录 RDB 文件生成后 master 收到的所有写命令。
当 RDB 文件传输完成并从节点加载后,主节点会将复制缓冲区中的所有写命令发送给从节点。
关于这个复制缓冲区,常见的配置如下:
client-output-buffer-limit <client-type> <hard-limit> <soft-limit> <soft-seconds>
# <client-type>:客户端类型,可以是 normal、replica 或 pubsub。
# <hard-limit>:硬限制,客户端的输出缓冲区大小达到此值时,连接将立即被断开。
# <soft-limit> 和 <soft-seconds>:软限制,客户端的输出缓冲区在 soft-seconds 秒内超过此值时,连接将被断开。
例如:
# 这个配置表示普通客户端的输出缓冲区没有任何限制,不会因为输出缓冲区过大而被断开。
client-output-buffer-limit normal 0 0 0
# normal:普通客户端(非复制客户端和非发布/订阅客户端)。
# 硬限制:0,表示不设硬限制。
# 软限制:0,表示不设软限制。
# 软秒数:0,表示不设软限制时间。
# 这个配置表示复制客户端的输出缓冲区有 256MB 的硬限制和 64MB/60秒的软限制。
client-output-buffer-limit replica 256mb 64mb 60
# replica:复制客户端(从节点)。
# 硬限制:256mb,如果复制客户端的输出缓冲区大小达到 256MB,连接将立即被断开。
# 软限制:64mb,如果复制客户端的输出缓冲区在 60 秒内超过 64MB,连接将被断开。
# 软秒数:60,软限制时间为 60 秒。
# 这个配置表示发布/订阅客户端的输出缓冲区有 32MB 的硬限制和 8MB/60秒的软限制
client-output-buffer-limit pubsub 32mb 8mb 60
# pubsub:发布/订阅客户端。
# 硬限制:32mb,如果发布/订阅客户端的输出缓冲区大小达到 32MB,连接将立即被断开。
# 软限制:8mb,如果发布/订阅客户端的输出缓冲区在 60 秒内超过 8MB,连接将被断开。
# 软秒数:60,软限制时间为 60 秒。
SYNC存在如下问题:
- slave 加载 RDB 的过程中不能对外提供读服务。
- slave 和 master 断开连接之后(本来master一直发命令给slave就好了),slave重新连上master需要重新进行全量同步。
1.2 增量同步-PSYNC
上面提到,命令传播的过程中,如果出现网络故障导致连接断开,此时新的写命令将无法同步到从库,slave重新连上master需要重新进行全量同步。
PSYNC 命令是 Redis 2.8 版本引入的一种用于主从复制的同步命令,解决了这个问题。
在从节点重新连接到主节点时,只会把断开的时候没有发生的写命令同步给从库,避免不必要的全量同步。
PSYNC <replicationid> <offset>
# <replicationid>:也叫runId,主节点的复制 ID(Replication ID),用于唯一标识主节点。
# <offset>:从节点的复制偏移量(Offset),表示从节点已经接收到的主节点数据的位置。
怎么解决断开后的同步问题呢?
-
master:记录自己写入缓冲区的偏移量(master_repl_offset),主库向从库发送 N 个字节的数据时,将自己的复制偏移量上加 N。
主节点会为每个从节点维护一个结构体(
replication
),该结构体包含从节点的复制偏移量、连接状态等信息。 -
slave:记录 master 的runId和自己的复制进度(偏移量slave_repl_offset),从库接收到主库发送的 N 个字节数据时,将自己的复制偏移量加上 N。
当redis节点启动时,会生成一个唯一的 runid
。
可以使用info命令查看。
- 初次同步:当从节点首次连接到主节点时,会通过
PSYNC ? -1
命令请求全量同步。主节点在响应中会返回其runid
和当前的复制偏移量。 - 部分重同步
- 如果从节点与主节点的连接断开并重新连接,从节点会发送
PSYNC <replicationid> <offset>
命令,其中replicationid
是主节点的runid
,offset
是从节点最后接收到的复制偏移量。 - 主节点检查从节点提供的
replicationid
是否与自己的runid
匹配。如果匹配,则根据偏移量决定是否可以进行部分重同步。
- 如果从节点与主节点的连接断开并重新连接,从节点会发送
那么,怎么找到两个offset之间的数据呢?
复制缓冲区(Replication Backlog)
复制缓冲区也称之为环形缓冲区,是用于支持主从复制中的部分重同步(Partial Resynchronization)。
环形缓冲区在设计上是一个固定大小的数组,写操作以循环的方式存储在其中。
当缓冲区写满时,新写操作会覆盖旧的写操作,这样可以有效利用内存,并确保主节点可以保存最近一段时间内的写操作记录。
环形缓冲区相关配置:
repl-backlog-size 1mb # 设置复制缓冲区的大小
repl-backlog-ttl 3600 # 设置复制缓冲区的生存时间(秒)
PSYNC存在如下问题:
- 主从切换或者主节点宕机等,runid和offset这些发生变化,依然需要进行全量同步。
1.3 增量同步-PSYNC2.0
2.为什么主从全量复制使用 RDB 而不是 AOF?
Redis 在主从全量复制中使用 RDB 而不是 AOF 的主要原因在于 RDB 文件具有传输效率高、一致性好、恢复速度快和简单性高的优点。
尽管 AOF 在持久化方面具有优势,但在初次同步和全量复制的场景下,RDB 文件能够更高效地完成数据传输和同步过程。
因此,Redis 选择使用 RDB 文件进行主从全量复制,以确保高效和一致的数据同步。
3.主从复制下从节点会主动删除过期数据吗?
在 Redis 的主从复制机制下,从节点(slave)不会主动删除过期数据。过期数据的处理是由主节点(master)负责的,然后将删除操作同步给从节点。
但是,但是。
我们主节点设置10s后过期 -> 发送给从节点执行 -> 从节点设置10s后过期
从节点是收到数据报文后才执行的,是有可能比主节点晚一丢丢过期的。
这种场景,可以不考虑使用指定ttl时间的方式,改为使用这两个命令:
在指定时间过期,注意保持各节点时间一致。
- EXPIREAT
- PEXPIREAT
1.2 哨兵Sentinel
在主从模式的场景下,一旦 master 宕机,我们需要从 slave 中手动选择一个新的 master,同时需要修改应用方的主节点地址,整个过程需要人工干预,十分麻烦。
通过哨兵模式,可以解决这个自动恢复的问题。
在主节点故障时,系统能够自动提升一个从节点为新的主节点,并且其他从节点会自动重新配置为新主节点的从节点。
注意哦,哨兵模式是主从模式的升级,让哨兵来帮我们做一些事情,所以我们得先配置好主从。
然后呢,这里有几个注意的点,先列举下,后文详细讲。
- 哨兵的数量不一定要和redis服务的数量一样。比如3个哨兵看5个服务也是能行的。
- 哨兵的数量最好为单数。1个哨兵肯定也是不合适的,加上单数的建议,所以一般最低3个。
1.2.1 实现
Sentinel 是一个独立于 Redis 服务器的进程,可以在不同的主机上运行。
查看我们redis安装后的可执行文件,可以发现,除了redis-server、redis-cli这些之外,还有一个redis-sentinel。
进程名 | 解释 | 默认端口 | 用处 |
---|---|---|---|
redis-server | Redis 服务器进程,负责存储和管理数据 | 6379 | 主要用于处理客户端请求,执行数据存储和查询操作 |
redis-cli | Redis 命令行客户端,用于与 Redis 服务器交互 | N/A | 用于手动管理和操作 Redis 数据库,执行各种 Redis 命令 |
redis-sentinel | Redis Sentinel 进程,监控和管理 Redis 集群 | 26379 | 监控 Redis 服务器的状态,自动进行故障转移,确保高可用性 |
哨兵模式,基本实现如下,sentinel 程序用于监控各个redis服务的状态,基本功能如下:
- 监控:监控所有 redis 节点(包括 sentinel 节点自身)的状态是否正常。
- 故障转移:如果一个 master 出现故障,sentinel 会帮助我们实现故障转移,自动将某一台 slave 升级为 master,确保整个 Redis 系统的可用性。
- 通知 :通知 slave 新的 master 连接信息,让它们执行 replicaof 成为新的 master 的 slave。
- 配置提供 :客户端连接 sentinel 请求 master 的地址,如果发生故障转移,sentinel 会通知新的 master 链接信息给客户端。
1.2.2 配置
下方演示一个1主2从3哨兵的配置。
类型 | 端口 | 配置文件 | 日志文件 | 说明 |
---|---|---|---|---|
master | 6379 | redis1.conf | redis1.log | redis主节点 |
slave1 | 6380 | redis2.conf | redis2.log | redis从节点1 |
slave2 | 6381 | redis3.conf | redis3.log | redis从节点2 |
sentinel1 | 26379 | sentinel1.conf | sentinel1.log | 哨兵1 |
sentinel2 | 26380 | sentinel2.conf | sentinel2.log | 哨兵2 |
sentinel3 | 26381 | sentinel3.conf | sentinel3.log | 哨兵3 |
上述文件,位于/yang/config/redis-sentinel
目录。
redis1、2、3文件夹用于存放redis的持久化文件,此处不用关注。
1.配置主从
参考上节主从复制的配置,主要是从节点上要配置主节点的信息。
1.1 主节点配置
# 运行端口
port 6379
# 以后台模式运行
daemonize yes
# 日志文件
logfile "/yang/config/redis-sentinel/redis1.log"
# 数据存储目录
dir "/yang/config/redis-sentinel/redis1"
1.2 从节点1配置
# 运行端口
port 6380
# 以后台模式运行
daemonize yes
# 从节点配置目标主节点
replicaof 127.0.0.1 6379
# 日志文件
logfile "/yang/config/redis-sentinel/redis2.log"
# 数据存储目录
dir "/yang/config/redis-sentinel/redis2"
# 如果主节点设置了密码,还需要在从节点配置文件中添加以下配置
# masterauth password
1.2 从节点2配置
# 运行端口
port 6381
# 以后台模式运行
daemonize yes
# 从节点配置目标主节点
replicaof 127.0.0.1 6379
# 日志文件
logfile "/yang/config/redis-sentinel/redis3.log"
# 数据存储目录
dir "/yang/config/redis-sentinel/redis3"
# 如果主节点设置了密码,还需要在从节点配置文件中添加以下配置
# masterauth password
2.配置哨兵
为每个 Sentinel 实例创建一个配置文件,主要是配置监控的主节点信息。
哨兵不需要配置从节点的信息,当 Sentinel 监控一个主节点时,它会自动发现与该主节点相关联的从节点。
节点的信息通过 Redis 内部的发布/订阅机制和 Sentinel 特有的协议进行传播,因此不需要在 Sentinel 配置文件中手动指定从节点。
2.1 哨兵1配置
# 哨兵运行端口
port 26379
# 以后台模式运行
daemonize yes
# 指定 Sentinel 的日志文件
logfile "/yang/config/redis-sentinel/sentinel1.log"
# 监控的主节点名称为 mymaster,地址为 127.0.0.1:6379,至少需要 2 个 Sentinel 同意认为主节点失效,才会进行故障转移
sentinel monitor mymaster 127.0.0.1 6379 2
# 主节点若配置了密码
# sentinel auth-pass mymaster xxx
# 主节点失效的判断时间(毫秒)
sentinel down-after-milliseconds mymaster 5000
# 故障转移超时时间(毫秒)
sentinel failover-timeout mymaster 60000
# 故障转移时同步的从节点数量
sentinel parallel-syncs mymaster 1
这里最后的parallel-syncs
咋理解馁?
当主节点出现故障时,哨兵会进行故障转移,将一个从节点提升为新的主节点。其他从节点需要同步新的主节点的数据。
如果配置为 sentinel parallel-syncs mymaster 1
,则:
-
哨兵会首先提升一个从节点为新的主节点。
-
其他从节点会按顺序一个一个地与新的主节点进行同步。
-
每次只有一个从节点与新的主节点同步。
同理,配置2就是同时2个,配置大了,不把你的主节点干懵啊。
2.2 哨兵2配置
# 哨兵运行端口
port 26380
# 以后台模式运行
daemonize yes
# 指定 Sentinel 的日志文件
logfile "/yang/config/redis-sentinel/sentinel2.log"
# 监控的主节点名称为 mymaster,地址为 127.0.0.1:6379,至少需要 2 个 Sentinel 同意认为主节点失效,才会进行故障转移
sentinel monitor mymaster 127.0.0.1 6379 2
# 主节点若配置了密码
# sentinel auth-pass mymaster xxx
# 主节点失效的判断时间(毫秒)
sentinel down-after-milliseconds mymaster 5000
# 故障转移超时时间(毫秒)
sentinel failover-timeout mymaster 60000
# 故障转移时同步的从节点数量
sentinel parallel-syncs mymaster 1
2.3 哨兵3配置
# 哨兵运行端口
port 26381
# 以后台模式运行
daemonize yes
# 指定 Sentinel 的日志文件
logfile "/yang/config/redis-sentinel/sentinel3.log"
# 监控的主节点名称为 mymaster,地址为 127.0.0.1:6379,至少需要 2 个 Sentinel 同意认为主节点失效,才会进行故障转移
sentinel monitor mymaster 127.0.0.1 6379 2
# 主节点若配置了密码
# sentinel auth-pass mymaster xxx
# 主节点失效的判断时间(毫秒)
sentinel down-after-milliseconds mymaster 5000
# 故障转移超时时间(毫秒)
sentinel failover-timeout mymaster 60000
# 故障转移时同步的从节点数量
sentinel parallel-syncs mymaster 1
3.启动主从
启动主从的redis服务。
redis-server redis1.conf
redis-server redis2.conf
redis-server redis3.conf
3.1 主节点日志
3.2 从节点1日志
3.3 从节点2日志
4.检查主从
当然咯,也可以结合主从配置那节讲的,检查一下。
4.1 主节点
4.2 从节点1
4.3 从节点2
5.启动哨兵
redis-sentinel sentinel1.conf
redis-sentinel sentinel2.conf
redis-sentinel sentinel3.conf
5.1 哨兵1启动日志
5.2 哨兵2启动日志
5.3 哨兵3启动日志
6.检查哨兵
使用命令连接到任一哨兵节点。
# 以26379端口所在节点的哨兵为例
redis-cli -p 26379
# 查看主节点信息
SENTINEL MASTER mymaster
# 或者一行
# redis-cli -p 26379 SENTINEL MASTER mymaster
# 查看从节点信息
SENTINEL SLAVES mymaster
# 或者一行
# redis-cli -p 26379 SENTINEL SLAVES mymaster
6.1 哨兵1
redis-cli -p 26379 SENTINEL MASTER mymaster
redis-cli -p 26379 SENTINEL SLAVES mymaster
6.2 哨兵2
redis-cli -p 26380 SENTINEL MASTER mymaster
redis-cli -p 26380 SENTINEL SLAVES mymaster
6.3 哨兵3
redis-cli -p 26381 SENTINEL MASTER mymaster
redis-cli -p 26381 SENTINEL SLAVES mymaster
6.4 扩展
6.4.1 连接异常
如果发现连接有问题,可以检查与主节点的通讯情况。
redis-cli -h 127.0.0.1 -p 6379 -a 密码 ping
正常应该相应PONG
。
6.4.2 字段含义
SENTINEL MASTER xx
主节点的健康状况等
参数名 | 含义 | 示例值 |
---|---|---|
name | 主节点的名称 | mymaster |
ip | 主节点的IP地址 | 127.0.0.1 |
port | 主节点的端口号 | 6379 |
runid | 主节点的唯一运行ID | d69c13604667476e5a6142195ab3f8bded4c8112 |
flags | 节点的标识(例如 master, slave, etc.) | master |
link-pending-commands | 等待发送的命令数量 | 0 |
link-refcount | 与主节点的链接引用计数 | 1 |
last-ping-sent | 上次发送ping命令的时间 | 0 |
last-ok-ping-reply | 上次ping命令成功回复的时间 | 452 |
last-ping-reply | 上次ping命令回复的时间 | 452 |
down-after-milliseconds | 认定主节点下线的毫秒数 | 5000 |
info-refresh | 信息刷新时间 | 9153 |
role-reported | 报告的角色(如 master) | master |
role-reported-time | 报告角色的时间 | 842336 |
config-epoch | 配置纪元,用于实现故障转移 | 0 |
num-slaves | 从节点的数量 | 2 |
num-other-sentinels | 监控此主节点的其他Sentinel数量 | 2 |
quorum | 达到法定人数所需的Sentinel数量 | 2 |
failover-timeout | 故障转移超时时间(毫秒) | 60000 |
parallel-syncs | 并行同步从节点的数量 | 1 |
SENTINEL SLAVES xx
从节点的健康状况以及它们与主节点的同步情况等
参数名 | 含义 | 示例值 |
---|---|---|
name | 从节点的名称 | 127.0.0.1:6381, 127.0.0.1:6380 |
ip | 从节点的IP地址 | 127.0.0.1 |
port | 从节点的端口号 | 6381, 6380 |
runid | 从节点的唯一运行ID | 4a386329851ef0c57f42bd0859ddf127e889b35b, d84d2fd171ef47503a53239e7fe6572c771e4b19 |
flags | 节点的标识(例如 master, slave, etc.) | slave |
link-pending-commands | 等待发送的命令数量 | 0 |
link-refcount | 与主节点的链接引用计数 | 1 |
last-ping-sent | 上次发送ping命令的时间 | 0 |
last-ok-ping-reply | 上次ping命令成功回复的时间 | 242 |
last-ping-reply | 上次ping命令回复的时间 | 242 |
down-after-milliseconds | 认定从节点下线的毫秒数 | 5000 |
info-refresh | 信息刷新时间 | 141 |
role-reported | 报告的角色(如 slave) | slave |
role-reported-time | 报告角色的时间 | 1124585, 1124590 |
master-link-down-time | 与主节点断开链接的时间 | 0 |
master-link-status | 主从链接状态 | ok |
master-host | 主节点的IP地址 | 127.0.0.1 |
master-port | 主节点的端口号 | 6379 |
slave-priority | 从节点的优先级 | 100 |
slave-repl-offset | 从节点的复制偏移量 | 221846 |
replica-announced | 从节点是否已被宣布 | 1 |
7.验证哨兵
7.1 停止主节点
停止主节点,观察哨兵是否会进行故障转移,并将从节点提升为新的主节点。
redis-cli -p 6379 shutdown
主节点日志
从节点1日志
从节点2日志
7.2 观察哨兵日志
哨兵1日志
哨兵2日志
哨兵3日志
7.3 查看从节点是否被提升为主节点
现在,我们的6379停止了,场上只剩下6380、6381两个从节点了。
从上面哨兵的日志中我们可以看到,原来的从节点2,即6381端口的被选为了新的主节点。
redis-cli -p 6381 info replication
去原来的从节点1上看下呢,可以看到他的主节点已经变成了新的主节点6381。
redis-cli -p 6380 info replication
8.总结
我们不妨让gpt对日志翻译下,简单了解下过程先。
8.1 从节点1
日志记录了从服务器与主服务器连接丢失后的多次重连尝试,均因连接被拒绝而失败。
(Sentinel 完成主服务器的故障转移后)从服务器成功切换到新的主服务器,并实现了部分重同步。
时间戳 | 日志条目 | 解释 |
---|---|---|
16:53:23.384 | Connection with master lost. |
与主服务器的连接丢失。 |
16:53:23.384 | Caching the disconnected master state. |
缓存断开连接时的主服务器状态。 |
16:53:23.384 | Reconnecting to MASTER 127.0.0.1:6379 |
尝试重新连接主服务器 127.0.0.1:6379 。 |
16:53:23.384 | MASTER <-> REPLICA sync started |
开始主从同步。 |
16:53:23.384 | Error condition on socket for SYNC: Connection refused |
同步过程中出现错误,连接被拒绝。 |
16:53:23.918 | Connecting to MASTER 127.0.0.1:6379 |
再次尝试连接主服务器 127.0.0.1:6379 。 |
16:53:23.918 | MASTER <-> REPLICA sync started |
再次开始主从同步。 |
16:53:23.918 | Error condition on socket for SYNC: Connection refused |
同步过程中再次出现错误,连接被拒绝。 |
16:53:24.921 | Connecting to MASTER 127.0.0.1:6379 |
第三次尝试连接主服务器 127.0.0.1:6379 。 |
16:53:24.921 | MASTER <-> REPLICA sync started |
第三次开始主从同步。 |
16:53:24.921 | Error condition on socket for SYNC: Connection refused |
同步过程中再次出现错误,连接被拒绝。 |
16:53:25.924 | Connecting to MASTER 127.0.0.1:6379 |
第四次尝试连接主服务器 127.0.0.1:6379 。 |
16:53:25.924 | MASTER <-> REPLICA sync started |
第四次开始主从同步。 |
16:53:25.924 | Error condition on socket for SYNC: Connection refused |
同步过程中再次出现错误,连接被拒绝。 |
16:53:26.928 | Connecting to MASTER 127.0.0.1:6379 |
第五次尝试连接主服务器 127.0.0.1:6379 。 |
16:53:26.928 | MASTER <-> REPLICA sync started |
第五次开始主从同步。 |
16:53:26.928 | Error condition on socket for SYNC: Connection refused |
同步过程中再次出现错误,连接被拒绝。 |
16:53:27.930 | Connecting to MASTER 127.0.0.1:6379 |
第六次尝试连接主服务器 127.0.0.1:6379 。 |
16:53:27.930 | MASTER <-> REPLICA sync started |
第六次开始主从同步。 |
16:53:27.931 | Error condition on socket for SYNC: Connection refused |
同步过程中再次出现错误,连接被拒绝。 |
16:53:28.933 | Connecting to MASTER 127.0.0.1:6379 |
第七次尝试连接主服务器 127.0.0.1:6379 。 |
16:53:28.934 | MASTER <-> REPLICA sync started |
第七次开始主从同步。 |
16:53:28.934 | Error condition on socket for SYNC: Connection refused |
同步过程中再次出现错误,连接被拒绝。 |
16:53:29.674 | Connecting to MASTER 127.0.0.1:6381 |
Sentinel 切换到新的主服务器 127.0.0.1:6381 并尝试连接。 |
16:53:29.674 | MASTER <-> REPLICA sync started |
开始与新的主服务器 127.0.0.1:6381 进行主从同步。 |
16:53:29.674 | REPLICAOF 127.0.0.1:6381 enabled (user request from 'id=7 addr=127.0.0.1:33494 laddr=127.0.0.1:6380 fd=11 name=sentinel-733d0299-cmd age=1299 idle=0 flags=x db=0 sub=0 psub=0 ssub=0 multi=4 qbuf=329 qbuf-free=16057 argv-mem=4 multi-mem=177 rbs=2328 rbp=1160 obl=45 oll=0 omem=0 tot-mem=19765 events=r cmd=exec user=default redir=-1 resp=2') |
执行 REPLICAOF 命令,将从服务器设置为 127.0.0.1:6381 的从服务器。 |
16:53:29.679 | CONFIG REWRITE executed with success. |
成功执行配置重写。 |
16:53:29.680 | Non blocking connect for SYNC fired the event. |
非阻塞同步事件触发。 |
16:53:29.680 | Master replied to PING, replication can continue... |
新的主服务器响应 PING 命令,复制可以继续进行。 |
16:53:29.680 | Trying a partial resynchronization (request fe81235de6312f933b404eef1fd3d4338e1331ff:255335). |
尝试部分重同步。 |
16:53:29.681 | Successful partial resynchronization with master. |
部分重同步成功。 |
16:53:29.681 | Master replication ID changed to 737583e70297e4140195fe1372c32acfa044f6de |
主服务器的复制 ID 改变。 |
16:53:29.681 | MASTER <-> REPLICA sync: Master accepted a Partial Resynchronization. |
主服务器接受了部分重同步。 |
8.2 从节点2
日志记录了从服务器与主服务器连接丢失后的多次重连尝试,均因连接被拒绝而失败。
(Sentinel 将从服务器切换为新的主服务器后)成功执行配置重写,新的主服务器接受了从服务器的部分重同步请求,并发送了积压的数据。
时间戳 | 日志条目 | 解释 |
---|---|---|
16:53:23.384 | Connection with master lost. |
与主服务器的连接丢失。 |
16:53:23.384 | Caching the disconnected master state. |
缓存断开连接时的主服务器状态。 |
16:53:23.384 | Reconnecting to MASTER 127.0.0.1:6379 |
尝试重新连接主服务器 127.0.0.1:6379 。 |
16:53:23.384 | MASTER <-> REPLICA sync started |
开始主从同步。 |
16:53:23.384 | Error condition on socket for SYNC: Connection refused |
同步过程中出现错误,连接被拒绝。 |
16:53:23.818 | Connecting to MASTER 127.0.0.1:6379 |
再次尝试连接主服务器 127.0.0.1:6379 。 |
16:53:23.818 | MASTER <-> REPLICA sync started |
再次开始主从同步。 |
16:53:23.818 | Error condition on socket for SYNC: Connection refused |
同步过程中再次出现错误,连接被拒绝。 |
16:53:24.821 | Connecting to MASTER 127.0.0.1:6379 |
第三次尝试连接主服务器 127.0.0.1:6379 。 |
16:53:24.822 | MASTER <-> REPLICA sync started |
第三次开始主从同步。 |
16:53:24.822 | Error condition on socket for SYNC: Connection refused |
同步过程中再次出现错误,连接被拒绝。 |
16:53:25.825 | Connecting to MASTER 127.0.0.1:6379 |
第四次尝试连接主服务器 127.0.0.1:6379 。 |
16:53:25.825 | MASTER <-> REPLICA sync started |
第四次开始主从同步。 |
16:53:25.825 | Error condition on socket for SYNC: Connection refused |
同步过程中再次出现错误,连接被拒绝。 |
16:53:26.829 | Connecting to MASTER 127.0.0.1:6379 |
第五次尝试连接主服务器 127.0.0.1:6379 。 |
16:53:26.829 | MASTER <-> REPLICA sync started |
第五次开始主从同步。 |
16:53:26.829 | Error condition on socket for SYNC: Connection refused |
同步过程中再次出现错误,连接被拒绝。 |
16:53:27.832 | Connecting to MASTER 127.0.0.1:6379 |
第六次尝试连接主服务器 127.0.0.1:6379 。 |
16:53:27.832 | MASTER <-> REPLICA sync started |
第六次开始主从同步。 |
16:53:27.832 | Error condition on socket for SYNC: Connection refused |
同步过程中再次出现错误,连接被拒绝。 |
16:53:28.743 | Discarding previously cached master state. |
丢弃先前缓存的主服务器状态。 |
16:53:28.743 | Setting secondary replication ID to fe81235de6312f933b404eef1fd3d4338e1331ff, valid up to offset: 255335. New replication ID is 737583e70297e4140195fe1372c32acfa044f6de |
设置次要复制 ID,并更新新的复制 ID。 |
16:53:28.743 | MASTER MODE enabled (user request from 'id=7 addr=127.0.0.1:47960 laddr=127.0.0.1:6381 fd=11 name=sentinel-733d0299-cmd age=1298 idle=0 flags=x db=0 sub=0 psub=0 ssub=0 multi=4 qbuf=188 qbuf-free=16198 argv-mem=4 multi-mem=169 rbs=1128 rbp=1112 obl=45 oll=0 omem=0 tot-mem=18557 events=r cmd=exec user=default redir=-1 resp=2') |
启用主服务器模式(根据用户请求)。 |
16:53:28.749 | CONFIG REWRITE executed with success. |
成功执行配置重写。 |
16:53:29.680 | Replica 127.0.0.1:6380 asks for synchronization |
从服务器 127.0.0.1:6380 请求同步。 |
16:53:29.680 | Partial resynchronization request from 127.0.0.1:6380 accepted. Sending 422 bytes of backlog starting from offset 255335. |
部分重同步请求被接受,并开始发送积压数据。 |
8.3 哨兵1
日志记录了 Sentinel 进行了一次主服务器 mymaster
的故障转移,并将新的主服务器设置为 127.0.0.1:6381
。
旧的主服务器 127.0.0.1:6379
变成了从服务器,并且在稍后的时间进入了主观下线状态等。
时间戳 | 日志条目 | 解释 |
---|---|---|
16:53:28.450 | +sdown master mymaster 127.0.0.1 6379 |
Sentinel 检测到主服务器 mymaster (IP: 127.0.0.1, 端口: 6379)进入主观下线状态。 |
16:53:28.548 | Sentinel new configuration saved on disk |
Sentinel 将新的配置保存到磁盘。 |
16:53:28.549 | +new-epoch 1 |
Sentinel 进入一个新的纪元(epoch)。 |
16:53:28.555 | Sentinel new configuration saved on disk |
Sentinel 将新的配置保存到磁盘。 |
16:53:28.556 | +vote-for-leader 733d0299e5d065a88516b90d27f1d8354e93c0ea 1 |
Sentinel 为新的领导者投票。 |
16:53:29.521 | +odown master mymaster 127.0.0.1 6379 #quorum 3/2 |
Sentinel 达到仲裁(quorum),将主服务器标记为客观下线状态。需要至少 2 个 Sentinel 同意主服务器下线,实际有 3 个 Sentinel 同意。 |
16:53:29.522 | Next failover delay: I will not start a failover before Wed Jun 5 16:55:29 2024 |
Sentinel 指定在 2024 年 6 月 5 日 16:55:29 之前不会开始故障转移。 |
16:53:29.674 | +config-update-from sentinel 733d0299e5d065a88516b90d27f1d8354e93c0ea 127.0.0.1 26380 @ mymaster 127.0.0.1 6379 |
从 Sentinel 733d0299e5d065a88516b90d27f1d8354e93c0ea 更新了配置,监控 mymaster (IP: 127.0.0.1, 端口: 6379)。 |
16:53:29.674 | +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6381 |
Sentinel 将主服务器从 127.0.0.1:6379 切换到 127.0.0.1:6381 。 |
16:53:29.674 | +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6381 |
从服务器 127.0.0.1:6380 重新配置为新的主服务器的从服务器。 |
16:53:29.674 | +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381 |
原来的主服务器 127.0.0.1:6379 现在成为新的主服务器的从服务器。 |
16:53:29.681 | Sentinel new configuration saved on disk |
Sentinel 将新的配置保存到磁盘。 |
16:53:34.715 | +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381 |
Sentinel 检测到从服务器 127.0.0.1:6379 进入主观下线状态。 |
8.4 哨兵2
日志记录了 Redis Sentinel 检测到主服务器下线,并完成故障转移的过程。
具体步骤包括检测主观下线,确认客观下线,进入新纪元,选举新领导者,选择新的主服务器,重新配置从服务器,最后完成故障转移等。
时间戳 | 日志条目 | 解释 |
---|---|---|
16:53:28.466 | +sdown master mymaster 127.0.0.1 6379 |
Sentinel 检测到主服务器 mymaster (IP: 127.0.0.1, 端口: 6379)进入主观下线状态。 |
16:53:28.533 | +odown master mymaster 127.0.0.1 6379 #quorum 2/2 |
Sentinel 达到仲裁(quorum),将主服务器标记为客观下线状态。需要至少 2 个 Sentinel 同意主服务器下线。 |
16:53:28.533 | +new-epoch 1 |
Sentinel 进入一个新的纪元(epoch)。 |
16:53:28.533 | +try-failover master mymaster 127.0.0.1 6379 |
Sentinel 开始对主服务器 mymaster 进行故障转移。 |
16:53:28.543 | Sentinel new configuration saved on disk |
Sentinel 将新的配置保存到磁盘。 |
16:53:28.543 | +vote-for-leader 733d0299e5d065a88516b90d27f1d8354e93c0ea 1 |
Sentinel 为新的领导者投票。 |
16:53:28.556 | e9c6df730b545bb8dab6df3dd83fc5bf382f9f87 voted for 733d0299e5d065a88516b90d27f1d8354e93c0ea 1 |
Sentinel 投票信息。 |
16:53:28.557 | 12310979f77d6b3c70a378b568576f780bfbcd6f voted for 733d0299e5d065a88516b90d27f1d8354e93c0ea 1 |
Sentinel 投票信息。 |
16:53:28.609 | +elected-leader master mymaster 127.0.0.1 6379 |
Sentinel 选举产生了新的领导者。 |
16:53:28.609 | +failover-state-select-slave master mymaster 127.0.0.1 6379 |
Sentinel 进入选择从服务器状态,开始选择新的主服务器。 |
16:53:28.672 | +selected-slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379 |
Sentinel 选择了从服务器 127.0.0.1:6381 作为新的主服务器。 |
16:53:28.672 | +failover-state-send-slaveof-noone slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379 |
Sentinel 发送 SLAVEOF NO ONE 命令,将选定的从服务器提升为主服务器。 |
16:53:28.743 | +failover-state-wait-promotion slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379 |
Sentinel 等待从服务器 127.0.0.1:6381 的提升过程完成。 |
16:53:29.579 | Sentinel new configuration saved on disk |
Sentinel 将新的配置保存到磁盘。 |
16:53:29.579 | +promoted-slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379 |
Sentinel 确认 127.0.0.1:6381 已经被提升为主服务器。 |
16:53:29.579 | +failover-state-reconf-slaves master mymaster 127.0.0.1 6379 |
Sentinel 开始重新配置其他从服务器。 |
16:53:29.674 | +slave-reconf-sent slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379 |
Sentinel 发送重新配置命令给从服务器 127.0.0.1:6380 。 |
16:53:30.605 | +slave-reconf-inprog slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379 |
从服务器 127.0.0.1:6380 的重新配置正在进行中。 |
16:53:30.605 | +slave-reconf-done slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379 |
从服务器 127.0.0.1:6380 的重新配置完成。 |
16:53:30.666 | -odown master mymaster 127.0.0.1 6379 |
Sentinel 取消主服务器的客观下线状态。 |
16:53:30.666 | +failover-end master mymaster 127.0.0.1 6379 |
Sentinel 完成故障转移。 |
16:53:30.666 | +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6381 |
Sentinel 将主服务器从 127.0.0.1:6379 切换到 127.0.0.1:6381 。 |
16:53:30.666 | +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6381 |
从服务器 127.0.0.1:6380 重新配置为新的主服务器的从服务器。 |
16:53:30.666 | +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381 |
原来的主服务器 127.0.0.1:6379 现在成为新的主服务器的从服务器。 |
16:53:30.672 | Sentinel new configuration saved on disk |
Sentinel 将新的配置保存到磁盘。 |
16:53:35.686 | +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381 |
Sentinel 检测到从服务器 127.0.0.1:6379 进入主观下线状态。 |
8.5 哨兵3
哨兵3与哨兵1类似
时间戳 | 日志条目 | 解释 |
---|---|---|
16:53:28.450 | +sdown master mymaster 127.0.0.1 6379 |
Sentinel 检测到主服务器 mymaster (IP: 127.0.0.1, 端口: 6379)进入主观下线状态。 |
16:53:28.548 | * Sentinel new configuration saved on disk |
Sentinel 将新的配置保存到磁盘。 |
16:53:28.549 | +new-epoch 1 |
Sentinel 进入一个新的纪元(epoch)。 |
16:53:28.555 | * Sentinel new configuration saved on disk |
Sentinel 将新的配置保存到磁盘。 |
16:53:28.556 | +vote-for-leader 733d0299e5d065a88516b90d27f1d8354e93c0ea 1 |
Sentinel 开始为新的领导者投票。 |
16:53:29.521 | +odown master mymaster 127.0.0.1 6379 #quorum 3/2 |
Sentinel 达到仲裁(quorum),将主服务器标记为客观下线状态。需要至少 2 个 Sentinel 同意主服务器下线,实际有 3 个 Sentinel 同意。 |
16:53:29.522 | Next failover delay: I will not start a failover before Wed Jun 5 16:55:29 2024 |
Sentinel 指定在 2024 年 6 月 5 日 16:55:29 之前不会开始故障转移。 |
16:53:29.674 | +config-update-from sentinel 733d0299e5d065a88516b90d27f1d8354e93c0ea 127.0.0.1 26380 @ mymaster 127.0.0.1 6379 |
从 Sentinel 733d0299e5d065a88516b90d27f1d8354e93c0ea 更新了配置,监控 mymaster (IP: 127.0.0.1, 端口: 6379)。 |
16:53:29.674 | +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6381 |
Sentinel 将主服务器从 127.0.0.1:6379 切换到 127.0.0.1:6381 。 |
16:53:29.674 | * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6381 |
从服务器 127.0.0.1:6380 重新配置为新的主服务器的从服务器。 |
16:53:29.674 | * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381 |
原来的主服务器 127.0.0.1:6379 现在成为新的主服务器的从服务器。 |
16:53:29.681 | * Sentinel new configuration saved on disk |
Sentinel 将新的配置保存到磁盘。 |
16:53:34.715 | +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381 |
Sentinel 检测到从服务器 127.0.0.1:6379 进入主观下线状态。 |
8.6 追加的配置文件
1.2.3 扩展
经过上面的例子,我们可以思考到如下问题。