天天看点

【Redis】主从复制(哨兵)

文章目录

    • 一、简介
    • 二、搭建redis集群
      • 1、实现伪集群
      • 2、复制三个redis.config文件
      • 3、配置redis63xx.config文件
    • 三、主从复制的复制原理
      • 1、开启三个redis服务
      • 2、命令实现主从复制(临时)
        • ① 设置6380和6381为6379的slave节点
        • ② 增量复制 测试
        • ③ 全量复制 测试
        • ④ slave写操作 测试
      • 3、配置文件实现主从复制(永久)
      • 4、复制原理
      • 5、全量同步与增量同步
    • 四、宕机后的手动配置主机
      • 1、简介
      • 2、搭建链式集群
      • 3、测试主从复制
      • 4、master宕机后手动配置master节点
    • 五、哨兵模式
      • 1、简介
      • 2、搭建单哨兵模式
        • 第一步:创建 sentinel.conf文件
        • 第二步:启动redis集群,配置号主从复制
        • 第三部:启动哨兵
        • 第四步:关闭6379redis服务
        • 第五步:重启6379redis服务
        • 总结
      • 3、完整的sentinel.conf文件
      • 4、搭建哨兵集群
        • 第一步:编写sentinel.conf配置文件
        • 第二步:启动三个redis-server服务
        • 第三步:启动三个redis-sentinel服务
        • 第四步:查看redis进程情况
        • 第五步:模仿master宕机的情况
      • 5、sentinel(哨兵)监控的工作原理

一、简介

和Mysql主从复制的原因一样,Redis虽然读取写入的速度都特别快,但是也会产生读压力特别大的情况。为了分担读压力,Redis支持主从复制,Redis的主从结构可以采用一主多从或者级联结构,Redis主从复制可以根据是否是全量分为全量同步和增量同步。

【Redis】主从复制(哨兵)

我们可以认为redis的主从复制是对master主机数据的一种备份。因为在实际的生产生活中难免会出现宕机的情况,面对这种情况,如果我们没有使用主从复制,那么将会导致长时间内数据我们取出(redis宕机)。

在redis的主从复制中,master主机是可以进行读写操作(以写为主)的,slave主机只能进行读操作(以读为主)。这是因为我们需要实现读写分离(在大并发的情况下提高性能)

二、搭建redis集群

正常情况下,我们在搭建集群的时候,是使用的不同的服务器,但是在这里我偷个懒,我在一个服务器上通过不同的端口号启动redis实现伪集群。

1、实现伪集群

我们测试的时候使用的是"一主儿从"的模式,我们需要创建一个master节点和两个slave节点。

为例实现上述的伪集群,我们需要复制三个redis.config启动文件,因为redis是依赖于redis.config的启动文件启动的,只要我们配置好redis.config中关于端口号的相关配置,就可以实现伪集群。

2、复制三个redis.config文件

[[email protected] ~]# cd /usr/local/bin/myconfig/
[[email protected] myconfig]# ls
redis6379.conf  redis6380.conf  redis6381.conf  redis.conf
[[email protected] myconfig]#
           

3、配置redis63xx.config文件

在这里我们就以redis6379.config为例,其他的文件操作一样。

配置端口

【Redis】主从复制(哨兵)

配置pid名称

【Redis】主从复制(哨兵)

配置log文件名

【Redis】主从复制(哨兵)

配置dump.rdb文件名

【Redis】主从复制(哨兵)

三、主从复制的复制原理

1、开启三个redis服务

通过上述的三个配置文件打开三个redis服务,默认情况下,每一台服务器都是主节点(我们可以通过

info replication

命令进行查看)

【Redis】主从复制(哨兵)
【Redis】主从复制(哨兵)
【Redis】主从复制(哨兵)

2、命令实现主从复制(临时)

我们可以使用命令的形式设置slave节点,但是这种方式的临时的,当redis重启之后,重启的redis又都是master角色了。

① 设置6380和6381为6379的slave节点

slaveof address port

该命令的作用是设置当前节点是哪个节点的slave,address表示master的地址,port表示master的端口号。

【Redis】主从复制(哨兵)
【Redis】主从复制(哨兵)
【Redis】主从复制(哨兵)

② 增量复制 测试

//在master节点中写入东西
127.0.0.1:6379> set name tiger
OK
127.0.0.1:6379> set age 18
OK


//在slave01中可以读到
127.0.0.1:6380> get age
"18"
127.0.0.1:6380> get name
"tiger"


//在slave02中也可以读到
127.0.0.1:6381> get age
"18"
127.0.0.1:6381> get name
"tiger"
           

③ 全量复制 测试

我们先让一个slave断开与master的连接

127.0.0.1:6381> SHUTDOWN
not connected> exit
[[email protected] bin]#
           

重启slave,测试是否能获取name

可以获取到name,说明salve已经将数据持久化了。

[[email protected] bin]# redis-server myconfig/redis6381.conf
[[email protected] bin]# redis-cli -p 6381
127.0.0.1:6381>  get name		//是可以获取到master中之前写入的name的
"tiger"
           

在master中写入gender,测试是否可以获取gender

127.0.0.1:6379> set gender man
OK
127.0.0.1:6379>
           

获取不到gender,因为此时6381不是master的slave。

127.0.0.1:6381> get gender
(nil)
           

从新连接slave与master,测试是否可以获取gender

重新连接后,我们是可以获取到在连接之前master写入的全部内容,说明连接之后,slave会同步master的所有的数据。

127.0.0.1:6381> slaveof 127.0.0.1 6379
OK
127.0.0.1:6381> get gender
"man"
127.0.0.1:6381>
[[email protected] bin]#

           

④ slave写操作 测试

我们尝试在slave中进行写操作,发现slave只是一个只读的替换,所以没有写的权限。

//slave01中不能进行写操作
127.0.0.1:6380> set gender man
(error) READONLY You can‘t write against a read only replica.

//slave0中也不能进行写操作
127.0.0.1:6381> set gender man
(error) READONLY You can't write against a read only replica.
           

3、配置文件实现主从复制(永久)

我们打开一个redisxxx.config文件,找到如下的位置,然后设置master的主机IP和端口号(有密码的设置上密码)就可以实现永久化的主从复制配置。

replicaof < masterip> < masterport>

   < masterip>:表示要跟随的master的IP

   < masterport>:表示要跟随的master的端口号

masterauth < master-password>

   < master-password>:表示要跟随的master的密码(没有就不用设置)

456 ################################# REPLICATION #################################
 457
 458 # Master-Replica replication. Use replicaof to make a Redis instance a copy of
 459 # another Redis server. A few things to understand ASAP about Redis replication.
 460 #
 461 #   +------------------+      +---------------+
 462 #   |      Master      | ---> |    Replica    |
 463 #   | (receive writes) |      |  (exact copy) |
 464 #   +------------------+      +---------------+
 465 #
 466 # 1) Redis replication is asynchronous, but you can configure a master to
 467 #    stop accepting writes if it appears to be not connected with at least
 468 #    a given number of replicas.
 469 # 2) Redis replicas are able to perform a partial resynchronization with the
 470 #    master if the replication link is lost for a relatively small amount of
 471 #    time. You may want to configure the replication backlog size (see the next
 472 #    sections of this file) with a sensible value depending on your needs.
 473 # 3) Replication is automatic and does not need user intervention. After a
 474 #    network partition replicas automatically try to reconnect to masters
 475 #    and resynchronize with them.
 
 //这个地方就是配置该redis将是谁的slave
 477 # replicaof <masterip> <masterport>   

 479 # If the master is password protected (using the "requirepass" configuration
 480 # directive below) it is possible to tell the replica to authenticate before
 481 # starting the replication synchronization process, otherwise the master will
 482 # refuse the replica request.

 //如果要跟随的master有密码,那么可以在这里设置
 484 # masterauth <master-password>		
           

个人认为这样方式用的也不多,因为这样方式会导致哨兵模式的失灵。

4、复制原理

salve启动连接到master后,会发一个sync(同步)命令。master接受到slave的同步命令后,启动后台存盘进程,同时收集所有接收到的用于修改数据的命令,在后台进程执行完毕后,master将传送整个数据文件到slave,完成一次完全(全量)同步。

【Redis】主从复制(哨兵)

5、全量同步与增量同步

只要slave重新连接master,那么就会完成一次完全(全量)同步,在slave连接master期间的同步是增量同步。

全量复制:全量复制用于salve启动第一次连接master主机时,同步master的全部数据。

增量复制:用于slave连接master后,持续同步master的新修改的数据。

四、宕机后的手动配置主机

1、简介

大家有没有思考过一个问题,以上述的模式,当我们的master节点崩了之后,我们的集群中就没有的master-slave的关系,这个问题我们可以怎么解决呢?

上面的主从复制的模式是一个,master有n个slave跟随。在这种模式下,当master节点宕机时,我们如果要是想要重新实现redis集群,显得很麻烦(我们需要从新设置master和slave的从属关系),尤其是slave的数量很多的时候。为例解决这种问题,我们需要使用另一种模式。

我们可以将redis集群中的节点通过链式结构进行部署,即master后面跟随一个slave01,slave01后面跟随slave02,…

【Redis】主从复制(哨兵)

2、搭建链式集群

① 启动三台redis服务

略…

② 配置链式集群

6380作为6379的slave

127.0.0.1:6380> slaveof 127.0.0.1 6379
OK
           

6381作为6380的slave

127.0.0.1:6381> slaveof 127.0.0.1 6380
OK

           

③ 查看集群的从属关系

6379作为master节点,下面有一个slave(6380)。

【Redis】主从复制(哨兵)

由下图,我们可以发现,及时6381将6380作为其mast节点,但是6380的角色依然是salve,这是因为6380仍然是6379的slave节点。但是下图显示6380有一个slave节点(6381)

【Redis】主从复制(哨兵)

由下图,我们知道6381是作为6380的slave存在的

【Redis】主从复制(哨兵)

3、测试主从复制

写入同步测试

//master节点中存入name
127.0.0.1:6379> set name studioustiger
OK

//master的直接从节点中是同步了name的
127.0.0.1:6380> get name
"studioustiger"

// 6380的直接从节点中也是同步了name的
127.0.0.1:6381> get name
"studioustiger"
           

清空同步测试

127.0.0.1:6379> flushdb
OK

127.0.0.1:6380> get name
(nil)

127.0.0.1:6381> get name
(nil)
           

4、master宕机后手动配置master节点

关闭 6379

127.0.0.1:6379> SHUTDOWN
not connected> exit
[[email protected] bin]#

           

查看6380的 info,发现其依然是slave节点,我们知道slave节点是不能进行写操作的。

127.0.0.1:6380> info replication
# Replication
role:slave						//还是6379的slave
master_host:127.0.0.1
master_port:6379
master_link_status:down
master_last_io_seconds_ago:-1
master_sync_in_progress:0
           

如果master节点出现宕机的情况,那么我们可以可以使用

slaveof no one

命令使原本的slave节点成为master节点。使其可以进行写操作。

127.0.0.1:6380> slaveof no one			//设置自己是master
OK
127.0.0.1:6380> info replication		
# Replication
role:master								//确实是6381的master
connected_slaves:1
slave0:ip=127.0.0.1,port=6381,state=online,offset=1038,lag=1
master_failover_state:no-failover
master_replid:58d09dee46e027f7696ce81c475e816eb56d688e
master_replid2:2ff752995921edd75b47e257435dbe952aa81d7f
master_repl_offset:1038
second_repl_offset:1039
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:1038
           

写入测试

//在新的master节点中写入数据
127.0.0.1:6380> set age 18
OK

//其从节点是可以同步的
127.0.0.1:6381> get age
"18"
           

五、哨兵模式

1、简介

经历过(四)中的手动配置,是不是就得很麻烦,而且上面的主从复制方法,我们并不会在实际的开发中去使用,上面的方式只是让我们更加的理解什么是主从复制。因为只有理解了上面的主从复制原理,那么对于接下来的哨兵模式才会游刃有余。所谓的哨兵模式就是一个起到监控的作用,当我们的master节点或slave节点发生宕机的情况的时候,我们需要通过某种机制实现监控的作用。

redis给我们提供了哨兵(sentinal)。sentinel是Redis官方推荐的高可用性(HA)解决方案。实际上这意味着你可以使用Sentinel模式创建一个可以不用人为干预而应对各种故障的Redis部署。

【Redis】主从复制(哨兵)

上图表现出的是三个redis服务器搭建的一个redis集群被一个哨兵所监控,当redis集群中的某一个节点发生宕机的情况,那么哨兵将会检查到,并且自动的选出新的节点。

上图中的模式还是有些不足,比如说,当哨兵宕机了那可咋办,所以我们需要对上面的模式进行改进——搭建一个哨兵的集群。如下图:

【Redis】主从复制(哨兵)

哨兵的三大功能:

  1. 监控(Monitoring): 哨兵(sentinel) 会不断地检查你的Master和Slave是否运作正常。
  2. 提醒(Notification):当被监控的某个 Redis出现问题时, 哨兵(sentinel) 可以通过 API 向管理员或者其他应用程序发送通知。
  3. 自动故障迁移(Automatic failover):当一个Master不能正常工作时,哨兵(sentinel) 会开始一次自动故障迁移操作,它会将失效Master的其中一个Slave升级为新的Master, 并让失效Master的其他Slave改为复制新的Master; 当客户端试图连接失效的Master时,集群也会向客户端返回新Master的地址,使得集群可以使用Master代替失效Master。

2、搭建单哨兵模式

搭建一个单哨兵模式还是比较简单的,我们使用单哨兵模式可以更好的看清楚哨兵的作用。

第一步:创建 sentinel.conf文件

创建 sentinel.conf文件(

vim sentinel.conf

【Redis】主从复制(哨兵)

编写sentinel.conf文件

# 哨兵sentinel实例运行的端口 默认26379
port 26379

sentinel monitor mymaster 127.0.0.1 6379 1
           

第二步:启动redis集群,配置号主从复制

启动redis集群

略…

配置号主从复制

【Redis】主从复制(哨兵)
【Redis】主从复制(哨兵)
【Redis】主从复制(哨兵)

第三部:启动哨兵

【Redis】主从复制(哨兵)

第四步:关闭6379redis服务

关闭6379redis服务

127.0.0.1:6379> SHUTDOWN
not connected> exit
[[email protected] bin]#
           

查看 6380和6381的info

发现6380仍然是slave节点

【Redis】主从复制(哨兵)

发现6381成为master节点了

【Redis】主从复制(哨兵)

查看sentinel节点的情况

原来是被sentinel节点监控到了,所以进行了重新选举,产生了新的master节点

【Redis】主从复制(哨兵)

第五步:重启6379redis服务

此时,你好不好奇,如果原本的master节点恢复了,那么原本的master节点将会以什么样的角色出现呢?我们来试一下

【Redis】主从复制(哨兵)

总结

当原本的master节点宕机之后,那么sentinel(哨兵)节点会监控到,并且会在剩余的slave节点中选举出新的master节点。当原本的master恢复之后,它只能作为新的master节点的从节点存在。

sentinel是选举master是通过相关的算法实现的,我们在这里先不讲。

3、完整的sentinel.conf文件

# Example sentinel.conf
 
# 哨兵sentinel实例运行的端口 默认26379
port 26379
 
# 哨兵sentinel的工作目录
dir /tmp
 
# 哨兵sentinel监控的redis主节点的 ip port 
# master-name  可以自己命名的主节点名字 只能由字母A-z、数字0-9 、这三个字符".-_"组成。
# quorum 当这些quorum个数sentinel哨兵认为master主节点失联 那么这时 客观上认为主节点失联了
# sentinel monitor <master-name> <ip> <redis-port> <quorum>
  sentinel monitor mymaster 127.0.0.1 6379 2
 
# 当在Redis实例中开启了requirepass foobared 授权密码 这样所有连接Redis实例的客户端都要提供密码
# 设置哨兵sentinel 连接主从的密码 注意必须为主从设置一样的验证密码
# sentinel auth-pass <master-name> <password>
sentinel auth-pass mymaster MySUPER--secret-0123passw0rd
 
 
# 指定多少毫秒之后 主节点没有应答哨兵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 <master-name> <numslaves>
sentinel parallel-syncs mymaster 1
 
 
 
# 故障转移的超时时间 failover-timeout 可以用在以下这些方面: 
#1. 同一个sentinel对同一个master两次failover之间的间隔时间。
#2. 当一个slave从一个错误的master那里同步数据开始计算时间。直到slave被纠正为向正确的master那里同步数据时。
#3.当想要取消一个正在进行的failover所需要的时间。  
#4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来了
# 默认三分钟
# sentinel failover-timeout <master-name> <milliseconds>
sentinel failover-timeout mymaster 180000
 
# SCRIPTS EXECUTION
 
#配置当某一事件发生时所需要执行的脚本,可以通过脚本来通知管理员,例如当系统运行不正常时发邮件通知相关人员。
#对于脚本的运行结果有以下规则:
#若脚本执行后返回1,那么该脚本稍后将会被再次执行,重复次数目前默认为10
#若脚本执行后返回2,或者比2更高的一个返回值,脚本将不会重复执行。
#如果脚本在执行过程中由于收到系统中断信号被终止了,则同返回值为1时的行为相同。
#一个脚本的最大执行时间为60s,如果超过这个时间,脚本将会被一个SIGKILL信号终止,之后重新执行。
 
#通知型脚本:当sentinel有任何警告级别的事件发生时(比如说redis实例的主观失效和客观失效等等),将会去调用这个脚本,
这时这个脚本应该通过邮件,SMS等方式去通知系统管理员关于系统不正常运行的信息。调用该脚本时,将传给脚本两个参数,
一个是事件的类型,
一个是事件的描述。
如果sentinel.conf配置文件中配置了这个脚本路径,那么必须保证这个脚本存在于这个路径,并且是可执行的,否则sentinel无法正常启动成功。
#通知脚本
# sentinel notification-script <master-name> <script-path>
  sentinel notification-script mymaster /var/redis/notify.sh
 
# 客户端重新配置主节点参数脚本
# 当一个master由于failover而发生改变时,这个脚本将会被调用,通知相关的客户端关于master地址已经发生改变的信息。
# 以下参数将会在调用脚本时传给脚本:
# <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
# 目前<state>总是“failover”,
# <role>是“leader”或者“observer”中的一个。 
# 参数 from-ip, from-port, to-ip, to-port是用来和旧的master和新的master(即旧的slave)通信的
# 这个脚本应该是通用的,能被多次调用,不是针对性的。
# sentinel client-reconfig-script <master-name> <script-path>
 sentinel client-reconfig-script mymaster /var/redis/reconfig.sh
 
           

4、搭建哨兵集群

通常情况下,我们会有一个哨兵集群,其目的是为了方式单个哨兵宕机之后,无法选举出新的节点,导致redis服务无法正常的执行。

我们在进行搭建sentinel集群是通常会选择奇数个sentinel节点,这是因为当master节点宕机之后,sentinel节点需要进行选举,如果我们搭建的是偶数个节点的集群,那么选举的时候可能会出现重票的情况。

正常情况下我们的redis集群不应该是在一台计算机上搭建的,但是我在这偷懒了,我们使用的是同一台虚拟机的不同的端口实现了伪集群。接下来我们将实现三个redis-server和三个redis-sentinel的redis集群。

第一步:编写sentinel.conf配置文件

sentinel1.conf:

# 哨兵sentinel实例运行的端口 默认26379
port 26379

# sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 127.0.0.1 6381 2
           

port:表示当前的sentinel服务开启时使用的端口号(默认为26379)。

< master-name>:表示redis集群中的master名字(自定义)。

< ip>:表示redis集群中的master的IP。

< redis-port>:表示redis集群中的master服务所占用的端口号。

< quorum>:表示当master节点宕机之后,需要几个sentinel节点确认才可以重新选举master。

sentinel2.conf:

# 哨兵sentinel实例运行的端口 默认26379
port 26380

# sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 127.0.0.1 6381 2
           

sentinel3.conf:

# 哨兵sentinel实例运行的端口 默认26379
port 26381

# sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 127.0.0.1 6381 2
           

第二步:启动三个redis-server服务

略…

值得注意的是,我们不需要使用手动配置master-slave,当发现集群中不存在master节点的时候,sentinel会自动进行选举。

第三步:启动三个redis-sentinel服务

启动第一个sentinel

【Redis】主从复制(哨兵)

启动第二个sentinel

【Redis】主从复制(哨兵)

启动第三个sentinel

【Redis】主从复制(哨兵)

第四步:查看redis进程情况

ps -ef | grep redis

【Redis】主从复制(哨兵)

第五步:模仿master宕机的情况

目前6381是master节点

【Redis】主从复制(哨兵)

关闭master节点

【Redis】主从复制(哨兵)

此时发现,6380成为了新的master节点

【Redis】主从复制(哨兵)

当6381恢复之后,我们看一下master和slave的情况。发现6381只能作为6380的slave节点存在。

【Redis】主从复制(哨兵)

5、sentinel(哨兵)监控的工作原理

哨兵 (sentinel) 是一个分布式系统,你可以在一个架构中运行多个哨兵(sentinel) 进程,这些进程使用流言协议 (gossipprotocols) 来接收关于Master是否下线的信息,并使用投票协议 (agreement protocols) 来决定是否执行自动故障迁移,以及选择哪个 Slave 作为新的 Master 。

每个哨兵 (sentinel) 会向其它哨兵 (sentinel)、master、slave定时发送消息,以确认对方是否”活”着,如果发现对方在指定时间(可配置)内未回应,则暂时认为对方已挂(所谓的”主观认为宕机” Subjective Down,简称 sdown).

若“哨兵群”中的多数 sentinel ,都报告某一 master 没响应(也就是为什么我们要设置 quorum 为 2 的原因),系统才认为该master"彻底死亡"(即:客观上的真正 down 机, Objective Down ,简称 odown ),通过一定的 vote 算法(从 slave 中选取 master 的算法),从剩下的 slave 节点中,选一台提升为 master ,然后自动修改相关配置。

今天的心情很复杂,五味杂陈。迷茫与不安并行,愿每一个年轻人为自己的选择负责到底 …

【Redis】主从复制(哨兵)

继续阅读