一.主从复制的问题
Redis 复制有一个缺点,当主机 Master 宕机以后,我们需要人工解决切换,比如使用slaveof no one 。实际上主从复制并没有实现,高可用, 高可用侧重备份机器, 利用集群中系统的冗余,当系统中某台机器发生损坏的时候,其他后备的机器可以迅速的接替它来启动服务
如下图所示:
一旦主节点宕机,写服务无法使用,就需要手动去切换,重新选取主节点,手动设置主从关系
那么如何解决呢?
如果我们有一个监控程序能够监控各个机器的状态及时作出调整,将手动的操作变成自动的。Sentinel(哨兵)的出现就是为了解决这个问题
二、哨兵机制的原理及实现
Redis Sentinel 是一个分布式架构,其中包含若干个 Sentinel 节点和 Redis 数据节点,每个 Sentinel 节点会对数据节点和其余 Sentinel 节点进行监控,当它发现节点不可达时,会对节点做下线标识。如果被标识的是主节点,它还会和其他 Sentinel 节点进行“协商”,当大多数 Sentinel 节点都认为主节点不可达时,它们会选举出一个 Sentinel 节点来完成自动故障转移的工作,同时会将这个变化实时通知给 Redis 应用方。整个过程完全是自动的,不需要人工来介入,所以这套方案很有效地解决了 Redis 的高可用问题。
如下图所示:
基本的故障转移流程:
1)主节点出现故障,此时两个从节点与主节点失去连接,主从复制失败。
2)每个 Sentinel 节点通过定期监控发现主节点出现了故障
3)多个 Sentinel 节点对主节点的故障达成一致会选举出其中一个节点作为领导者负责故障转移。
4)Sentinel 领导者节点执行了故障转移,整个过程基本是跟我们手动调整一致的,只不过是自动化完成的。
5)故障转移后整个 Redis Sentinel 的结构,重新选举了新的主节点
三.Redis Sentinel 具有以下几个功能:
-
监控:Sentinel 节点会定期检测 Redis 数据节点、其余 Sentinel 节点是否可达。
-
通知:Sentinel 节点会将故障转移的结果通知给应用方。
-
主节点故障转移:实现从节点晋升为主节点并维护后续正确的主从关系。
-
配置提供者:在 Redis Sentinel 结构中,客户端在初始化的时候连接的是 Sentinel 节点集合,从中获取主节点信息
同时Redis Sentinel 包含了若个 Sentinel 节点,这样做也带来了两个好处: 对于节点的故障判断是由多个 Sentinel 节点共同完成,这样可以有效地防止误判。 Sentinel 节点集合是由若干个 Sentinel 节点组成的,这样即使个别 Sentinel 节点不可用,整个 Sentinel 节点集合依然是健壮的。 但是 Sentinel 节点本身就是独立的 Redis 节点,只不过它们有一些特殊,它们不存储数据,只支持部分命令
四.利用docker配置redis的主从复制,redis-sentinel哨兵
docker 环境下安装redis具体参考:https://blog.youkuaiyun.com/yinjinshui/article/details/102561445
4.1 redis主从节点,sentinel节点
容器名称 | 容器ip地址 | 映射端口 | 服务运行模式 |
---|---|---|---|
redis-master | 172.168.0.3 | 6381->6379 | master |
redis-slave1 | 172.168.0.4 | 6382->6379 | slave |
redis-slave2 | 172.168.0.5 | 6383->6379 | slave |
redis-sentinel1 | 172.168.0.9 | 22530->26379 | sentinel |
redis-sentinel2 | 172.168.0.10 | 22531->26379 | sentinel |
redis-sentinel3 | 172.168.0.11 | 22532->26379 | sentinel |
创建redis容器,sentinel容器:
1.创建redis-master节点:
[root@localhost Dockerfile]# docker run -itd --name redis-master --net rediswork -p 6381:6379 --ip 172.168.0.3 redis
7343a77b3e73e5f833a2c3fb2a18d5921635749e329aeaa1e854fe3295180834
2.创建redis-slave1节点:
[root@localhost Dockerfile]# docker run -itd --name redis-slave1 --net rediswork -p 6382:6379 --ip 172.168.0.4 redis
03070a588707c346f58b5b652fa443079da658d53343b24205dc0e7fc45f75b9
3.创建redis-slave2节点:
[root@localhost Dockerfile]# docker run -itd --name redis-slave2 --net rediswork -p 6383:6379 --ip 172.168.0.5 redis
84cc33a574311b6ca56b486a2510a0bd0860469fd96b0b3603788514b1feee66
4.创建redis-sentinel1节点:
[root@localhost Dockerfile]# docker run -itd --name redis-sentinel1 --net rediswork -p 22530:26379 --ip 172.168.0.9 redis
043867d7f405524aef9cb3db83b8807d766ab64f464391844f9021eefaad556b
5.创建redis-sentinel2节点:
[root@localhost Dockerfile]# docker run -itd --name redis-sentinel2 --net rediswork -p 22531:26379 --ip 172.168.0.10 redis
72da3510e697b288ea03b2e35335d8648f32e50d8eab6190c6383b9176ee5680
6.创建redis-sentinel3节点:
[root@localhost Dockerfile]# docker run -itd --name redis-sentinel3 --net rediswork -p 22532:26379 --ip 172.168.0.11 redis
02fabf77bb1f27d1f67a79deff8942aa48a756b68a63e432cb94cbf0de5ba96e
查看容器:
4.2配置redis-slave从节点配置文件
#进入redis-slave1节点:
[root@localhost Dockerfile]# docker exec -it redis-slave1 bash
[root@03070a588707 /]# find / -name redis.conf
/etc/redis.conf
find: '/proc/1/map_files': Operation not permitted
find: '/proc/13/map_files': Operation not permitted
find: '/proc/25/map_files': Operation not permitted
#修改配置文件
[root@03070a588707 /]# vi /etc/redis.conf
================================================
#进入redis-slave2节点:
[root@localhost Dockerfile]# docker exec -it redis-slave2 bash
[root@84cc33a57431 /]# find / -name redis.conf
/etc/redis.conf
find: '/proc/1/map_files': Operation not permitted
find: '/proc/13/map_files': Operation not permitted
find: '/proc/25/map_files': Operation not permitted
#修改配置文件
[root@84cc33a57431 /]# vi /etc/redis.conf
修改的【从节点redis-slave1,redis-slave2】配置文件:
4.3修改redis-master配置文件
#进入主节点
[root@localhost Dockerfile]# docker exec -it redis-master bash
[root@7343a77b3e73 /]# vi /etc/redis.conf
#启动redis-server
[root@7343a77b3e73 /]# redis-server /etc/redis.conf &
#进入redis客户端
[root@7343a77b3e73 /]# redis-cli
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:0
master_replid:df94d252f7c2b990b2d1b4fb8466890b5da36c28
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:6379>
4.4启动redis-slave1,redis-slave2从节点
#启动redis-slave1节点的redis-server:
[root@03070a588707 /]# redis-server /etc/redis.conf &
[1] 41
#启动redis-slave2节点的redis-server:
[root@84cc33a57431 /]# redis-server /etc/redis.conf &
[1] 61
4.5 redis-master 查看从节点是否连接上
127.0.0.1:6379> info replication
4.6 查看从节点连接信息
redis-slave2节点信息:
redis-slave1从节点信息:
五.配置redis-sentinel哨兵【注意哨兵节点需要3台机器以上】
5.1进入哨兵容器,修改哨兵配置文件(redis-sentinel.conf)
#进入哨兵1修改配置文件
[root@localhost ~]# docker exec -it redis-sentinel1 bash
[root@043867d7f405 /]# vi /etc/redis-sentinel.conf
#进入哨兵2修改配置文件
[root@localhost ~]# docker exec -it redis-sentinel2 bash
[root@72da3510e697 /]# vi /etc/redis-sentinel.conf
#进入哨兵3修改配置文件
[root@localhost ~]# docker exec -it redis-sentinel3 bash
[root@02fabf77bb1f /]# vi /etc/redis-sentinel.conf
修改的配置文件内容如下【截图】
5.2 启动哨兵
#启动哨兵1
[root@043867d7f405 /]# redis-sentinel /etc/redis-sentinel.conf &
[1] 41
#启动哨兵2
[root@72da3510e697 /]# redis-sentinel /etc/redis-sentinel.conf &
[1] 34
#启动哨兵3
[root@02fabf77bb1f /]# redis-sentinel /etc/redis-sentinel.conf &
[1] 26
5.4 进入哨兵客户端
#进入哨兵客户端1:
[root@043867d7f405 /]# redis-cli -p 26379
127.0.0.1:26379>
#进入哨兵客户端2:
[root@72da3510e697 /]# redis-cli -p 26379
127.0.0.1:26379>
#进入哨兵客户端3:
[root@02fabf77bb1f /]# redis-cli -p 26379
127.0.0.1:26379>
六.当前模拟redis-master 宕机了
#重启了redis-master的容器
[root@localhost src]# docker restart redis-master
redis-master
redis容器主从复制的截图信息:
结论:redis-master宕机之后,哨兵会重新选取redis-master 主节点服务器
==========================================
7.Sentinel 的核心配置(redis-sentinel.conf):
详细说明可参考redis手册:http://redisdoc.com/topic/sentinel.html#
sentinel monitor mymaster 172.10.0.3 6379 2
指示 Sentinel 去监视一个名为 mymaster 的主服务器, 这个主服务器的 IP 地址为 172.10.0.3, 端口号为 6379 , 而将这个主服务器判断为失效至少需要 2 个 Sentinel 同意 (只要同意 Sentinel 的数量不达标,自动故障迁移就不会执行)。
对于设置的越小,那么达到下线的条件越宽松,反之越严格。一般建议将其设置为 Sentinel 节点的一半加1
注意:
最后的参数不得大于conut(sentinel)
sentinel down-after-milliseconds mymaster 60000
指定了 Sentinel 认为服务器已经断线所需的毫秒数。
如果服务器在给定的毫秒数之内, 没有返回 Sentinel 发送的 PING 命令的回复, 或者返回一个错误, 那么 Sentinel 将这个服务器标记为主观下线(subjectively down,简称 SDOWN )。
不过只有一个 Sentinel 将服务器标记为主观下线并不一定会引起服务器的自动故障迁移: 只有在足够数量的 Sentinel 都将一个服务器标记为主观下线之后, 服务器才会被标记为客观下线(objectively down, 简称 ODOWN ), 这时自动故障迁移才会执行。
将服务器标记为客观下线所需的 Sentinel 数量由对主服务器的配置决定。
这个是超时的时间(单位为毫秒)。打个比方,当你去 ping 一个机器的时候,多长时间后仍 ping 不通,那么就认为它是有问题
sentinel parallel-syncs mymaster 5
指定了在执行故障转移时, 最多可以有多少个从服务器同时对新的主服务器进行同步, 这个数字越小, 完成故障转移所需的时间就越长
当 Sentinel 节点集合对主节点故障判定达成一致时,Sentinel 领导者节点会做故障转移操作,选出新的主节点,原来的从节点会向新的主节点发起复制操作,parallel-syncs 就是用来限制在一次故障转移之后,每次向新的主节点发起复制操作的从节点个数,指出 Sentinel 属于并发还是串行。1代表每次只能复制一个,可以减轻 Master 的压力;
sentinel auth-pass <master-name> <password>
如果 Sentinel 监控的主节点配置了密码,sentinel auth-pass 配置通过添加主节点的密码,防止 Sentinel 节点对主节点无法监控。
sentinel failover-timeout mymaster 180000
表示故障转移的时间。
8.Sentinel 命令
SENTINEL masters**
列出所有被监视的主服务器,以及这些主服务器的当前状态
127.0.0.1:26379> sentinel masters
SENTINEL slaves <master name>
列出给定主服务器的所有从服务器,以及这些从服务器的当前状态
127.0.0.1:26379> sentinel slaves mymaster
SENTINEL master <master name>
显示指定master的信息和状态
127.0.0.1:26379> sentinel master mymaster
SENTINEL get-master-addr-by-name <master name>
返回指定master的ip和端口,如果正在进行failover或者failover已经完成,将会显示被提升为master的slave的ip和端口
127.0.0.1:26379> sentinel get-master-addr-by-name mymaster
SENTINEL failover <master name>
当主服务器失效时, 在不询问其他 Sentinel 意见的情况下, 强制开始一次自动故障迁移
(不过发起故障转移的 Sentinel 会向其他 Sentinel 发送一个新的配置,其他 Sentinel 会根据这个配置进行相应的更新)
修改配置
sentinel monitor test 127.0.0.1 6379 2 添加新的监听
SENTINEL REMOVE test 放弃对某个master监听
SENTINEL set failover-timeout mymaster 180000 设置配置选项