Redis主从和哨兵模式

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
主从复制原理:
  1. 初次全量同步

当一个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执行这些写命令。

  1. 命令传播

slave已经同步过master,后续master进行写操作时,master执行过当前命令后,会将当前命令发送给slave执行一遍,达成数据一致性。

  1. slave断开

重连之后会进行重新同步,重新同步分完全同步和部分同步

1
2
3
4
a.当slave断开重连后,会发送psync命令给master(PSYNC [主服务器 ID] [复制偏移量])。[复制偏移量]是上一次同步的位置,用于定位具体的同步位置的.
b.master收到psync,并找到相应同步的位置后,后会返回+continue回复,表示slave可以执行部分同步了。
c.master发送断线后的写命令给slave。
d.slave执行写命令。

注意:使用主从复制,主节点的redis必须开启持久持久化, 否则,如果主redis一旦重启,导致主节点数据丢失,然后会将从节点上的数据也全部清空,这种灾难是毁灭级的。另外需要注意主从数据不一致问题、复制超时问题、复制缓冲区溢出问题。

读写分离:

分离方式

1.主从库区分,从SLAVEOF开始。主从库模式开启之后,读写就已经分离了,应用层面采用读写分离,所有数据的写操作只会在主库上进行,而读操作基本会在从库上进行

2.redis.conf配置

1
2
3
4
5
#replicaof <masterip> <masterport> # 配置主节点 ip 和端口
replicaof 192.168.1.189 6379
#masterauth <master-password> # 配置 masterauth 主节点密码
masterauth 123456
replica-read-only yes # 设置 从节点只读

重启

1
>info replication //查看redis信息

主节点不挂,从节点保持slave状态,主节点挂机,从节点保持slave状态,不会自动选举成为master。

主从+读写分离就可以实现负载均衡

2.Redis哨兵模式Sentinel

主从模式,若主服务器宕机了,就得人工干预,选择一台从服务器重新作为主服务器,然后将另外的几台从服务器的配置文件修改一下,将replicaof的配置重新改成新的主服务器地址。人工干预费时费力不说,更重要的是,这样会造成一段时间内服务是不可用的。在这种场景下,哨兵模式应运而生了。

sentinel主要有以下功能:

1
2
3
4
1.集群监控:负责监控 Redis master 和 slave 进程是否正常工作。
2.消息通知:如果某个 Redis 实例有故障,那么哨兵负责发送消息作为报警通知给管理员。
3.故障转移:如果 master node 挂掉了,会自动转移到 slave node 上。
4.配置中心:如果故障转移发生了,通知 client 客户端新的 master 地址。
  • 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
2
3
4
5
6
主节点哨兵:
6379端口redis主服务,哨兵默认端口为26379

从节点哨兵:
7001端口redis服务,哨兵使用27001端口
7002端口redis服务,哨兵使用27002端口

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
2
3
4
5
6
include sentinel.conf
pidfile /var/run/sentinel_26380.pid
port 26380
sentinel monitor mymaster 192.168.11.10 6380 2
# 192.168.11.10是Redis服务器的IP地址
# logfile access26380.log

sentinel26380.conf文件保存退出后,在新建sentinel26381.conf和sentinel26382.conf这两个文件,文件内容就是上面的内容,只不过要把所有的26380改为26381和26382即可。

D.启动并关联redis集群

1
2
3
4
5
6
7
8
9
10
>redis-cli -p 6380
127.0.0.1:6380>auth 1233333

>redis-cli -p 6381
127.0.0.1:6381>auth 1233333
127.0.0.1:6381>replicaof 127.0.0.1:6380

>redis-cli -p 6382
127.0.0.1:6382>auth 1233333
127.0.0.1:6382>replicaof 127.0.0.1:6380

6380是主,26381和2638是从

E.启动Sentinel集群

命令行中启动哨兵实例的两种方式,一是直接运行 redis-sentinel 命令,另一种是运行 redis-server 命令并且参数中含有 --sentinel 参数。

1
2
方式一:redis-sentinel sentinel26380.conf
方式二:redis-server sentinel26380.conf --sentinel

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为止。