Redis 是一款开源的、内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。然而,作为一个单点服务,Redis 在面临硬件故障或者网络问题时可能会导致服务不可用。为了解决这个问题,Redis 提供了哨兵模式,一个高可用性解决方案。
在这篇博客中,我们将深入探讨 Redis 的哨兵模式。我们将首先介绍哨兵模式的基本概念,包括主节点、从节点和哨兵节点。然后,我们将详细解析哨兵模式下的主要流程,包括主观下线、客观下线、领导者选举和故障转移。
无论你是一个 Redis 的新手,还是一个有经验的开发者,我相信这篇博客都能帮助你更好地理解和使用 Redis 的哨兵模式。让我们开始吧!
Redis 哨兵模式是 Redis 提供的一种高可用解决方案。它通过使用哨兵节点来监控 Redis 主服务器和从服务器的运行状态,当主服务器出现故障时,哨兵可以自动将一个从服务器提升为新的主服务器,实现故障转移。
以下是 Redis 哨兵模式的主要特点:
主从复制模式在 Redis 中是一种常见的数据冗余和读取性能提升的方式,但它也存在一些不足之处:
Redis 哨兵模式就是为了解决这些问题而设计的:
在 Redis 哨兵模式中,主要有以下三种角色:
在哨兵模式下,主节点、从节点和哨兵节点都可以是多个,形成一个分布式的、高可用的 Redis 服务。
哨兵模式是通过哨兵节点完成对数据节点的监控、下线、故障转移。
哨兵节点会定期检查主服务器和所有从服务器的运行状态,包括是否在线,是否能正常响应请求,主从数据复制是否正常等。
以下是哨兵模式下的定时监控的主要步骤:
__sentinel__:hello
频道发送消息,这个消息包含了该 Sentinel 节点对于主节点的判断以及当前 Sentinel 节点的信息;在 Redis 哨兵模式中,"主观下线"和"客观下线"是两个重要的概念,它们是 Sentinel 节点判断主服务器是否出现故障的依据。
主观下线(Subjective Down):每个 Sentinel 节点会定期(默认是每1秒)向主节点、从节点和其他 Sentinel 节点发送 PING 命令进行心跳检测。如果某个节点在 down-after-milliseconds
参数设定的时间内没有进行有效回复,Sentinel 节点就会对该节点做失败判定,这个行为被称为主观下线。
主观下线是基于 Sentinel 节点自身视角的判断,它只代表了该 Sentinel 节点无法与被检测节点正常通信,可能是由于网络问题或者被检测节点的实际故障。
客观下线(Objective Down):当足够多的 Sentinel 节点都认为主服务器已经下线,那么主服务器就被认为是客观下线。这是多数 Sentinel 节点的共识,更具有可信度。
在 Redis 哨兵模式中,当一个 Sentinel 节点主观判断主节点下线后,它会通过 sentinel is-master-down-by-addr
命令向其他 Sentinel 节点询问对主节点的判断。如果收到的回复中,认为主节点下线的 Sentinel 节点数量达到了 quorum
参数设定的值,那么这个 Sentinel 节点就会认为主节点确实有问题,做出客观下线的决定。
在 Sentinel 模式下,只有当主服务器被判断为客观下线,才会触发故障转移过程。这是为了防止由于个别 Sentinel 节点的网络问题或者误判导致的误报。只有当多数 Sentinel 节点都认为主服务器已经下线,才认为这是一个真实的故障,需要进行故障转移。
在 Redis 哨兵模式中,当主节点被判断为客观下线后,哨兵节点会进行领导者选举,选出一个领导者 Sentinel 节点来负责故障转移的过程。以下是领导者 Sentinel 节点选举的详细步骤:
通过这个过程,哨兵系统可以在主节点出现故障后,快速选举出一个领导者来进行故障转移,保证 Redis 服务的高可用性。
在 Redis 哨兵模式中,当主节点被判断为客观下线后,哨兵节点会进行故障转移,选举一个新的主节点,并重新配置从节点。以下是故障转移的详细步骤:
SLAVEOF NO ONE
命令,让它成为新的主节点。SLAVEOF
命令,让它们成为新主节点的从节点。+switch-master
事件的客户端发送消息,通知它们主节点已经切换。通过这个过程,哨兵系统可以在主节点出现故障后,快速完成故障转移,保证 Redis 服务的高可用性。
拉取 Redis 镜像:
docker pull redis
创建所需文件夹,用于映射容器相应文件路径:
mkdir -p ~/data/redis/master/data
touch ~/data/redis/master/redis.confmkdir
touch ~/data/redis/master/redis.conf
mkdir -p ~/data/redis/slave-1/data
touch ~/data/redis/slave-1/redis.confmkdir
touch ~/data/redis/slave-1/redis.conf
mkdir -p ~/data/redis/slave-2/data
touch ~/data/redis/slave-2/redis.confmkdir
touch ~/data/redis/slave-2/redis.conf
mkdir -p ~/data/redis/slave-3/data
touch ~/data/redis/slave-3/redis.confmkdir
touch ~/data/redis/slave-3/redis.conf
# sentinel.conf 文件一个就够
touch ~/data/redis/master/sentinel.conf
修改主节点 redis.conf 文件
bind 0.0.0.0
# 开启保护模式,限制为本地访问,默认yes
protected-mode no
# 默认no,改为yes意为以守护进程方式启动,可后台运行,除非kill进程,改为yes会使配置文件方式启动redis失败
daemonize no
# redis持久化(可选)
appendonly yes
修改从节点 redis.conf 文件
bind 0.0.0.0
# 开启保护模式,限制为本地访问,默认yes
protected-mode no
# 默认no,改为yes意为以守护进程方式启动,可后台运行,除非kill进程,改为yes会使配置文件方式启动redis失败
daemonize no
# redis持久化(可选)
appendonly yes
# 指向master节点
replicaof 172.17.0.2 6379
修改 sentinel.conf 文件
daemonize yes
sentinel monitor mymaster 172.17.0.2 6379 2
port 26379
运行容器并指定挂载路径:
docker run -p 16379:6379 -p 16389:26379 --name redis-master -v ~/data/redis/master/data/:/data -v ~/data/redis/master/sentinel.conf:/etc/redis/sentinel.conf -v ~/data/redis/master/redis.conf:/etc/redis/redis.conf -d redis redis-server /etc/redis/redis.conf --appendonly yes
---
docker run -p 26379:6379 -p 16390:26379 --name redis-slave-1 -v ~/data/redis/slave-1/data/:/data -v ~/data/redis/slave-1/sentinel.conf:/etc/redis/sentinel.conf -v ~/data/redis/slave-1/redis.conf:/etc/redis/redis.conf -d redis redis-server /etc/redis/redis.conf --appendonly yes
---
docker run -p 36379:6379 -p 16391:26379 --name redis-slave-2 -v ~/data/redis/slave-2/data/:/data -v ~/data/redis/slave-2/sentinel.conf:/etc/redis/sentinel.conf -v ~/data/redis/slave-2/redis.conf:/etc/redis/redis.conf -d redis redis-server /etc/redis/redis.conf --appendonly yes
---
docker run -p 46379:6379 -p 16392:26379 --name redis-slave-3 -v ~/data/redis/slave-3/data/:/data -v ~/data/redis/slave-3/sentinel.conf:/etc/redis/sentinel.conf -v ~/data/redis/slave-3/redis.conf:/etc/redis/redis.conf -d redis redis-server /etc/redis/redis.conf --appendonly yes
通过 Docker Desktop 查看:
查看主从节点信息:
# 进入从节点服务
docker exec -it [CONTAINER ID] redis-cli
# 查看角色信息
127.0.0.1:6379> role
# 查看主从复制信息
127.0.0.1:6379> info replication
主节点:
从节点: