Redis高可用3种模式
主从模式(Master-Slave Replication)、哨兵模式(Sentinel Mode)、集群模式(Cluster Mode)
1.redis主从复制的实现:
主服务器为127.0.0.1 6379,从服务器为127.0.0.1:12345,在主服务器中写入数据,从服务器可以直接获取,删除数据也是类似。
1 | 127.0.0.1:12345> SLAVEOF 127.0.0.1 6379 |
主从复制原理:
- 初次全量同步
当一个redis服务器初次向主服务器发送salveof命令时,redis从服务器会进行一次全量同步。
1)slave服务器向master发送psync命令(发送psync ? -1),告诉master需要同步数据。
2)master接收到psync命令后会进行BGSAVE命令生成RDB文件快照,并记录"积压缓冲区"从现在开始执行的所有写命令。RDB文件生成完后,会将其发送给slave。
3)slave接收到文件会载入RDB快照,并且将数据库状态变更为master在执行BGSAVE时的状态一致。
4)master发送记录的"积压缓冲区"写命令,告诉slave可以进行同步了,slave执行这些写命令。
- 命令传播
slave已经同步过master,后续master进行写操作时,master执行过当前命令后,会将当前命令发送给slave执行一遍,达成数据一致性。
- slave断开
重连之后会进行重新同步,重新同步分完全同步和部分同步
1 | a.当slave断开重连后,会发送psync命令给master(PSYNC [主服务器 ID] [复制偏移量])。[复制偏移量]是上一次同步的位置,用于定位具体的同步位置的. |
注意:使用主从复制,主节点的redis必须开启持久持久化, 否则,如果主redis一旦重启,导致主节点数据丢失,然后会将从节点上的数据也全部清空,这种灾难是毁灭级的。另外需要注意主从数据不一致问题、复制超时问题、复制缓冲区溢出问题。
读写分离:
分离方式
1.主从库区分,从SLAVEOF
开始。主从库模式开启之后,读写就已经分离了,应用层面采用读写分离,所有数据的写操作只会在主库上进行,而读操作基本会在从库上进行
2.redis.conf配置
1 | #replicaof <masterip> <masterport> # 配置主节点 ip 和端口 |
重启
1 | >info replication //查看redis信息 |
主节点不挂,从节点保持slave状态,主节点挂机,从节点保持slave状态,不会自动选举成为master。
主从+读写分离就可以实现负载均衡
2.Redis哨兵模式Sentinel
主从模式,若主服务器宕机了,就得人工干预,选择一台从服务器重新作为主服务器,然后将另外的几台从服务器的配置文件修改一下,将replicaof的配置重新改成新的主服务器地址。人工干预费时费力不说,更重要的是,这样会造成一段时间内服务是不可用的。在这种场景下,哨兵模式应运而生了。
sentinel主要有以下功能:
1 | 1.集群监控:负责监控 Redis master 和 slave 进程是否正常工作。 |
-
sentinel哨兵是特殊的redis服务,不提供读写服务,主要用来监控redis实例节点。
这里的,redis的client端一般都实现了订阅功能,订阅sentinel发布的节点变动消息。 -
redis实现了发布订阅(publish/subscribe)的功能,但是在通常的情况下是不推荐使用的,最好还是使用专业的各种MQ中间件,例如rabbitMQ等。因为客户端必须一直在线才能接收到消息,断线可能会导致客户端丢失消息,除此之外,旧版的redis可能会由于订阅者消费不够快而变的不稳定导致崩溃,甚至被管理员杀掉。
redis的哨兵模式:
一主多从情况下,主服务器宕机了,自动将从服务器中的一台设为新的master,并且将其余的slave的配置文件自动修改,这样就切换出一套新的主从服务,不需要人工干预,且不会影响服务的使用。减少系统不能提供服务的时间,这就是哨兵模式要解决的最重要的问题。
哨兵是一个独立于主从服务之外的集群服务。哨兵实例会不断给主服务器发送Ping命令,主服务器在收到命令后,返回一个有效回复,这样哨兵实例认为服务器是正常的。
主观下线:
假设主服务器宕机,哨兵1在指定时间内(可配置)没有收到主服务器的有效回复,那么这个哨兵会把服务器标记为下线,叫做主观下线SDOWN。
注意此时只有一个哨兵标记为下线,实际上哨兵没有收到回复原因可能有很多,可能是服务器确实挂了,也有可能是服务器并没有挂,由于网络原因没有收到回复,总之,一个哨兵没有收到回复并不能证明主服务器宕机。
客观下线:
哨兵2也发送了Ping命令,同样也没有收到回复,哨兵2也会将主服务器标记为SDOWN。这个时候,3个哨兵中有2个哨兵上报了SDOWN,哨兵们在彼此交流之后(一个 Sentinel 可以通过向另一个 Sentinel 发送 SENTINEL is-master-down-by-addr 命令来询问对方是否认为给定的服务器已下线。),认为已经有足够数量的实例证明该服务已经不可用,因此,哨兵实例会将该服务器标记为客观下线ODOWN。
这里的足够数量是可配置的,一般是哨兵个数的一半加1,比如3个哨兵则就设置为2。
投票选举,故障转移:
当哨兵实例将服务标记为客观下线时,会进行一次选举。在剩下的从服务器实例中,选出一个作为主节点,并同时修改其余从服务器的配置文件,将新的主节点作为数据同步的来源,然后重新启动服务,完成切换。
至此,一个完整的哨兵自动进行故障转移的过程就完成了。
故障转移步骤:
执行命令slaveof no one关闭复制,从节点变更为主节点。
其余从节点slaveof new master变更成新的master的从节点。
notice client:故障转移后sentinel结点会将结果通知给客户端(应用方)。
原主节点恢复后变成从节点去复制新的主节点信息。
哨兵搭建
哨兵需要独立的服务器,对应Redis集群的服务器数量,在此为实验性质,因此在redis集群的服务器上搭建哨兵,实现所谓的“伪集群”。类似于:
1 | 主节点哨兵: |
A.sentinel.conf 文件
Redis集群,Redis 安装目录中的 sentinel.conf 文件复制到 cluster 目录,该配置文件中用于存放一些 sentinel 集群中的一些公共配置。Redis源码包中包含了一个sentinel.conf文件作为sentinel的配置文件。
sentinel.conf是其配置文件,每当redis集群发生变化时,配置文件会被Sentinel服务所改写,因此该配置文件实时记录了redis集群当前状态。如果Sentinel被重启,它也可以通过该配置文件了解到redis集群的当前状态,并和其它Sentinel服务共同提供服务
B.修改配置文件
cluster/sentinel.conf 配置文件
sentinel monitor
< master-name > < ip > < redis-port > max(quorum, sentinelNum/2+1)
1 | sentinel monitor mymaster 127.0.0.1 6379 3 |
master-name:Sentinel 要监控的 master名称,该名字在后面很多配置中都会使用。quorum:指定 Sentinel 集群中决定master“客观下线”的 sentinel 数量,
max:sentinel参与选举数量范围
sentinel auth-pass
1 | sentinel auth-pass mymaster 1233333 |
如果 Redis 主从集群中的主机设置了访问密码,那么该属性就需要指定 master 的主机名与访问密码。以方便 sentinel 监控 master。
C.新建Sentinel 的配置文件
在 redis 目录下的 cluster 目录中新建 sentinel26380.conf 文件作为 Sentinel 的配置文件,并在其中键入如下内容
1 | include sentinel.conf |
sentinel26380.conf文件保存退出后,在新建sentinel26381.conf和sentinel26382.conf这两个文件,文件内容就是上面的内容,只不过要把所有的26380改为26381和26382即可。
D.启动并关联redis集群
1 | >redis-cli -p 6380 |
6380是主,26381和2638是从
E.启动Sentinel集群
命令行中启动哨兵实例的两种方式,一是直接运行 redis-sentinel 命令,另一种是运行 redis-server 命令并且参数中含有 --sentinel 参数。
1 | 方式一:redis-sentinel sentinel26380.conf |
2个命令本质上是同一个命令,但可以启动不同的进程,主要是因为在启动时所加载的配置文件的不同,所以在启动 Sentinel 时,需要指定 sentinel.conf 配置文件。
F.查看Sentinel信息
运行中的 Sentinel 就是一个特殊 Redis,其也可以通过客户端连接,然后通过 info sentinel来查看当前连接的 Sentinel 的信息。
1 | >redis-cli -p 26380 info sentinel |
G.查看Sentinel配置文件
查看端口号为26830的Sentinel的配置文件
H哨兵优化配置
Sentinel服务搭建,需要安装
Sentinel间的交流和选举:
1.当有Sentinel服务发现服务器主观下线后,会向其他Sentinel发送SENTINEL is-master-down-by-addr命令,并且命令中的runid参数不是*符号而是源Sentinel的运行ID,这表示源Sentinel要求目标Sentinel将源Sentinel设置为目标Sentinel的局部领头Sentinel。通常,最先向目标Sentinel发送设置要求的源Sentinel将成为局部领头,即先到先得。
2.目标Sentinel在接收到is-master-down-by-addr命令后,将向源Sentinel返回一条命令,包含了目标Sentinel的局部领头Sentinel的运行ID(leader_runid)和配置纪元。源Sentinel接收到目标Sentinel返回的命令回复后,会检查返回的配置纪元是否与自己的相同,如果相同,再检查leader_runid是否和自己的runid一致,如果一致那么久表示目标将源Sentinel设置成了局部领头Sentinel。
3如果被半数以上的Sentinel设置成了局部领头,且达到了配置的quonum,那么这个Sentinel就成为了领头Sentinel,在一个配置纪元里面,只会出现一个领头Sentinel。无论选举是否成功,所有Sentinel的配置纪元(configuration epoch)的值都会加1。若没选举出来,则再一段时间后将再次进行选举,直到选出领头Sentinel为止。