1. Redis 高可用的几种方案
- 主从模式
- 特点:一主多从,数据异步复制,主节点宕机需手动切换。
- 适用场景:可用性不高,基本不使用。
- 哨兵模式
- 特点:哨兵集群监控主节点,主节点宕机自动实现故障转移。但写操作仍受单主节点限制,并且每个节点存储的数据相同,内存空间利用率不高。
- 适用场景:中小规模生产环境。
- 集群模式
- 特点:数据分片(16384 slots),多主多从,解决了单点故障同时最大限度利用了内存,实现了真正的分布式,支持水平扩展。
- 使用场景:大规模高并发生产环境。
2. 主从模式
2.1. 架构
- 数据流向:主节点异步复制数据到从节点。
- 读写分离:写请求仅主节点,读请求可分流到从节点。
2.2. 配置方式
主节点配置文件示例:
# /etc/redis/redis.conf
# 基础配置
daemonize yes
bind 0.0.0.0
port 6379
# 考虑到后续主从可能会发生切换,所以为了方便建议无论主从节点最开始都在 redis.conf 中配置上这两项且保持密码一致
masterauth 123456
requirepass 123456
# masterauth:连接主库用的密码,是主库里设置的密码
# requirepass:自己的密码
Bash从节点配置示例:
# 基础配置
daemonize yes
bind 0.0.0.0
port 6379
# 配置主节点的ip和端口
slaveof 192.168.71.12 6379
# 从redis2.6开始,从节点默认是只读的
slave-read-only yes
masterauth 123456
requirepass 123456
Bash可以登录主或从节点查看主从状态:
info replication
Bash主节点宕机,手动切换:
# 选择一个从节点提升为新主节点
redis-cli -h <slave-ip> -p <port> SLAVEOF NO ONE
# 配置其他从节点复制新的主节点
redis-cli -h <other-slave-ip> -p <port> SLAVEOF <new-master-ip> <port>
# 恢复宕机的主节点,并作为从节点指向新的主节点,同时按照现在的构架修改主从节点的配置文件。
Bash3. 哨兵模式
哨兵模式是为了解决主从模式无法自动故障切换而诞生的,把下图的哨兵节点去掉后就是主从模式,哨兵集群主要用来实现自动故障切换。
3.1. 架构
- 至少 3 个 Sentinel 节点。
- 自动检测主节点故障并选举新主。
3.2. 哨兵的作用
哨兵是特殊的 Redis 服务,不提供读写服务,主要用来监控 Redis 实例节点。
- 监控:哨兵会不断地检查 Master 和 Slave 是否运作正常。
- 提醒(通知):当被监控的某个 Redis 节点出现问题时,哨兵可以通过 API 向管理员或者其他应用程序发送通知。
- 自动故障转移:当一个 Master 不能正常工作时,哨兵进行自动故障切换操作,将一个 Slave 升级为新的 Master,并让其他 Slave 改为复制新的Master;当客户端试图连接失效的 Master 时,哨兵也会向客户端返回新Master 的地址。
3.3. 配置示例
建议将哨兵进程和 Redis 分别部署在不同的机器上,避免因为 Redis 宕机导致sentinel 进程不可用。
每台机器的哨兵进程都需要一个哨兵的配置文件 sentinel.conf,三台机器的哨兵配置是一样的。完整配置如下:
# /etc/redis/sentinel.conf
# 常规配置,目录需要先创建好
bind 0.0.0.0
port 26379
daemonize yes
pidfile /var/run/redis-sentinel.pid
loglevel notice
logfile "/soft/sentinel/sentinel.log"
dir "/soft/sentinel/data"
# 禁止保护模式,保护模式是增强 redis 安全防止未经授权的客户端访问 redis 实例
protected-mode no
# 各部分解释
# (1)sentinel monitor: 代表监控
# (2)mymaster:给主节点起的名称(自定义标识符),后续所有针对这个主节点的 Sentinel 配置都要使用相同的名称。只能由字母A-z、数字0-9 、这三个字符".-_"组成
# (3)192.168.71.101 6379:被监控的主节点(Master)的 ip 与 port
# (4)2:判定主节点"客观下线"所需的最小 Sentinel 同意数量,当至少 2 个 Sentinel 实例认为主节点不可达时,才会触发故障转移流程。
sentinel monitor mymaster 192.168.71.101 6379 2
# mymaster:主节点的名称(必须与 sentinel monitor 中定义的名称一致)。
# 123456:主节点(Master)的 Redis 密码(即 requirepass 设置的密码),如果主节点没有密码,则不需要配置这一行。
sentinel auth-pass mymaster 123456
# 定义 Sentinel 判定主节点(Master)"主观下线"的等待时间。如果 Sentinel 在 30秒(30000毫秒) 内无法与主节点正常通信(如 PING 无响应),则该 Sentinel 独自 认为主节点"主观下线"。
sentinel down-after-milliseconds mymaster 30000
# 限制全量同步(SYNC)的并发数
## 当 Sentinel 选举出新主节点后,所有从节点需要与它重新同步数据(全量或增量同步)。
## parallel-syncs 控制同时执行同步的从节点数量(默认值为 1)。
## 该参数的作用是避免主节点过载,如果所有从节点同时同步,可能导致主节点性能骤降,甚至二次故障。
sentinel parallel-syncs mymaster 2
# 主备切换的超时时间,哨兵要去做故障转移,这个时候哨兵也是一个进程,如果他没有去执行,超过这个时间后,会由其他的哨兵来处理
sentinel failover-timeout mymaster 180000
# 限制 ACL(访问控制列表)日志的最大条目数。
## 记录认证失败、权限拒绝等安全事件。
## 当日志达到 1024 条后,旧记录会被新事件覆盖。
acllog-max-len 1024
# 禁止通过 Sentinel 自动修改主节点的脚本配置。
sentinel deny-scripts-reconfig yes
# 禁用 Sentinel 对主机名的 DNS 解析。
SENTINEL resolve-hostnames no
# 禁止 Sentinel 向客户端和从节点通告主机名。
SENTINEL announce-hostnames no
# 禁用主节点重启时的特殊下线检测逻辑。
## 默认情况下,Sentinel 会对重启的主节点启用一个额外的等待期(防止误判)。
## 设置为 0 表示 主节点重启后立即被视为下线,不等待额外检测。
SENTINEL master-reboot-down-after-period mymaster 0
BashPython 代码连接哨兵:
# pip3 install redis # 安装完就可以用 redis.sentinel了
from redis.sentinel import Sentinel
# 配置哨兵(Sentinels)的地址和端口,这里为了演示,配置了3个哨兵
sentinels = [('192.168.71.101', 26379), ('192.168.71.102', 26379),('192.168.71.103', 26379)]
# 创建Sentinel实例。socket_timeout是连接超时时间
sentinel = Sentinel(sentinels, socket_timeout=2000)
# 获取主节点的连接对象,其中'mymaster'是你的哨兵配置中定义的名字
master = sentinel.master_for('mymaster', socket_timeout=2000, db=0, password="123456")
# 获取从节点的连接对象
slave = sentinel.slave_for('mymaster', socket_timeout=2000, db=0, password="123456")
# 在主节点上执行写操作(你的主从发生切换,master底层会自动变,不需要你关心master变成了谁)
master.set('mykey', 'myvalue')
# 在从节点上执行读操作
value = slave.get('mykey')
print(value) # 应当输出: myvalue
Python4. 集群模式
4.1. 架构
4.2. 工作原理
集群模式是 Redis 的一种高可用实现方式,它通过数据分片和分布式存储实现了负载均衡和高可用性。在集群模式下,Redis 将所有的键值对数据分散在多个节点上。每个节点负责一部分数据,称为槽位。通过对数据的分片,集群模式可以突破单节点的内存限制,实现更大规模的数据存储。
数据分片与槽位:Redis Cluster 将数据分为 16384 个槽位,每个节点负责管理一部分槽位。当客户端向 Redis Cluster 发送请求时,Cluster 会根据键的哈希值将请求路由到相应的节点。具体来说,Redis Cluster 使用 CRC16 算法计算键的哈希值,然后对 16384 取模,得到槽位编号。
集群模式的读写:集群模式下主节点负责读和写,从库只负责备份。
客户端连接 Redis 集群:对客户端来说,整个 Cluster 被看做是一个整体。客户端可以连接任意一个 node 进行操作,当客户端操作的 key 没有分配到该 node 上时,Redis 会返回转向指令,指向正确的 node。如果请求指向 slave 节点,也会直接重定向到对应 key 所在的 master 来处理。
4.3. 配置示例
根据官方推荐,集群部署至少要3台以上的 master 节点,每个 master 节点至少一个 slave 节点。
开启集群模式配置文件示例:
# 每个节点配置文件相同
daemonize yes
bind 0.0.0.0
protected-mode no
# 开启集群模式
cluster-enabled yes
# 节点超时时间
cluster-node-timeout 15000
Bash创建集群:
# 创建集群(主从自动分配)
redis-cli --cluster create \
节点1IP:端口 节点2IP:端口 节点3IP:端口 \
节点4IP:端口 节点5IP:端口 节点6IP:端口 \
--cluster-replicas 1 # 每个主节点配1个从节点
Bash客户端连接集群:
# 选择任一节点
redis-cli -c -h 节点IP -p 端口 # -c,使用集群方式登录,有密码的话就在加上参数 -a 123456
# 查看集群信息
CLUSTER INFO # 查看集群信息
CLUSTER NODES # 列出节点信息
Bash4.4. 集群模式扩容
# 1.准备新节点
## 在新服务器上安装相同版本的 Redis。
## 配置文件保持相同。
# 2.添加主节点
## 启动新节点。
## 将节点加入集群。
redis-cli --cluster add-node <新节点IP>:<端口> <现有集群任意节点IP>:<端口>
## 重新分配哈希槽
redis-cli --cluster reshard <现有集群任意节点IP>:<端口>
# 按照提示操作
> 1000 # 迁移1000个槽
> 3c3a0c74aae0b56170ccb03a76b60cfe7d... # 新节点ID
> all # 从所有节点迁移
> yes # 确认配置
# 3.添加从节点
## 启动新节点。
## 将节点加入集群。
redis-cli --cluster add-node <新节点IP>:<端口> <现有集群任意节点IP>:<端口> --cluster-slave --cluster-master-id <目标主节点ID>
Bash注意事项:
- 数据迁移影响:
- 重新分片期间集群仍可正常服务。
- 迁移单个key时会阻塞该key的访问(毫秒级)。
- 建议操作时间:
- 选择业务低峰期进行操作。
- 大数据量迁移建议分批执行。