07 Sentinel
一. 主从复制高可用
# 主从复制存在的问题:
1. 主节点发生故障,需要做故障转移,可以手动转移:让其中一个slave变成master
2. 只能主写数据,所以写能力和存储能力有限
二. 架构说明
Sentinel作用
1. 可以做故障判断,故障转移
2. 可以通知客户端(其实是一个进程),客户端直接连接sentinel的地址
sentinel故障转移流程
1. 多个sentinel发现并确认master有问题
2. 选举触一个sentinel作为领导
3. 选取一个slave作为新的master
4. 通知其余slave成为新的master的slave
5. 通知客户端主从变化
6. 等待老的master复活成为新master的slave
三. 安装配置
1. sentinel配置
# 基本配置参数
# 配置端口
port 26379
# 是否后台运行
daemonize yes
# 配置存储目录
dir "/opt/redis-5.0.7/data/"
# 是否设置保护模式
protected-mode no
# 配置连接IP地址
bind 0.0.0.0
# 配置日志文件存储位置
logfile "redis_sentinel.log"
# sentinel主要配置
# 告诉sentinel去监听IP地址为127.0.0.1 port为6379的master,这里的master-name可以自定义,quorum(指派)当有多少个sentinel认为一个master失效时,master才算真正失效.
# sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 127.0.0.1 6379 2
# 这个配置项指定了需要多少失效时间,一个master才会被这个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 mymaster 1
# 1. 同一个sentinel对同一个master两次failover(故障转移)之间的间隔时间。
# 2. 当一个slave从一个错误的master那里同步数据开始计算时间。直到slave被纠正为向正确的master那里同步数据时。
# 3. 当想要取消一个正在进行的failover(故障转移)所需要的时间。
# 4. 当进行failover(故障转移)时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来了。
sentinel failover-timeout mymaster 180000
# sentinel其他配置
# 设置连接master和slave时的密码,注意的是sentinel不能分别为master和slave设置不同的密码,因此master和slave的密码应该设置相同。
# 设置连接master和slave时的密码,注意的是sentinel不能分别为master和slave设置不同的密码,因此master和slave的密码应该设置相同。
sentinel auth-pass <master-name> <password>
2. 简单示例
目的: 搭建1主2从 和 3个哨兵进行监控
"""搭建1主2从"""
# 主: 6379
vim /opt/redis/conf/redis_6379.conf
daemonize yes
port 6379
dir "/opt/redis/data/"
logfile "redis_6381.log"
protected-mode no
pidfile /var/run/redis_6379.pid
# 从: 6380
vim /opt/redis/conf/redis_6380.conf
daemonize yes
port 6380
pidfile /var/run/redis_6380.pid
dir "/opt/redis/data/"
logfile "redis_6381.log"
protected-mode no
slaveof 127.0.0.1 6379
slave-read-only yes
# 从: 6381
vim /opt/redis/conf/redis_6381.conf
daemonize yes
port 6381
pidfile /var/run/redis_6381.pid
dir "/opt/redis/data/"
logfile "redis_6381.log"
protected-mode no
slaveof 127.0.0.1 6379
slave-read-only yes
# 启动1主2从服务器
redis-server /opt/redis/conf/redis_6379.conf
redis-server /opt/redis/conf/redis_6380.conf
redis-server /opt/redis/conf/redis_6381.conf
# 客户端连接
redis-server -p 6379
redis-server -p 6380
redis-server -p 6381
"""搭建3个哨兵"""
# 哨兵: 26379 监控 6379(主)
vim /opt/redis/conf/redis_sentinel_26379.conf
port 26379
daemonize yes
dir "/opt/redis/data/"
protected-mode no
bind 0.0.0.0
logfile "redis_sentinel_26379.log"
sentinel monitor mymaster 10.0.0.100 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
# 哨兵: 26380 监控 6380(从)
vim /opt/redis/conf/redis_sentinel_26380.conf
port 26380
daemonize yes
dir "/opt/redis/data/"
protected-mode no
bind 0.0.0.0
logfile "redis_sentinel_26380.log"
sentinel monitor mymaster 10.0.0.100 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
# 哨兵: 26381 监控 6381(从)
vim /opt/redis/conf/redis_sentinel_26381.conf
port 26381
daemonize yes
dir "/opt/redis/data/"
protected-mode no
bind 0.0.0.0
logfile "redis_sentinel_26381.log"
sentinel monitor mymaster 10.0.0.100 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
# 启动哨兵
redis-sentinel /opt/redis/conf/redis_sentinel_26379.conf
redis-sentinel /opt/redis/conf/redis_sentinel_26380.conf
redis-sentinel /opt/redis/conf/redis_sentinel_26381.conf
# 登陆哨兵
redis-cli -p 26379
redis-cli -p 26380
redis-cli -p 26381
# 登录哨兵以后查看状态
info
# 主动停掉主redis 6379,哨兵会自动选择一个从库作为主库
redis-cli -p 6379
shutdown
四. 客户端连接
import redis
from redis.sentinel import Sentinel
# 连接哨兵服务器有几个哨兵就写几个哨兵的连接IP和端口
sentinel = Sentinel(
[
('10.0.0.100', 26379),
('10.0.0.100', 26380),
('10.0.0.100', 26381)
],
socket_timeout=5)
print(sentinel) # Sentinel<sentinels=[10.0.0.100:26379,10.0.0.100:26380,10.0.0.100:26381]>
# 获取主服务器地址: mymaster是配置文件中自定义的master-name
master = sentinel.discover_master('mymaster')
print(master)
# 获取从服务器地址
slave = sentinel.discover_slaves('mymaster')
print(slave)
"""读写分离"""
# 获取主服务器进行写入
master = sentinel.master_for('mymaster', socket_timeout=0.5)
w_res = master.set('name', 'yang')
slave = sentinel.slave_for('mymaster', socket_timeout=0.5)
r_res = slave.get('name')
print(r_res)