Redis学习(八)————深入了解Redis主从复制,Redis哨兵机制

一、什么是Redis主从复制?

在这里插入图片描述
将一台服务器作为Redis的主库(Master),另外服务器作为从库(Slave)(一台或多台)。主库(Master)只负责写数据,每次有数据更新的时候,Redis服务器会将数据从主库同步到其他从库中,从库只负责读取数据。
一个主库可以拥有多个从库,一个从库只能拥有一个主库,一个从库也可以拥有从库,但从库依然还是从库,不会拥有写的功能。

二、为什么要Redis复制?

1、尽管Redis的性能很优秀,但它也会遇到没办法快速处理请求的情况,特别是在对集合和有序集合进行操作的时候,涉及到的元素可能会有上万个甚至上百万,在这种情况下执行所花费的时间可能以秒来计算,而不是毫秒或者微秒。但即使一个命令只需要花费10毫秒就能完成,单个redis实例1s也只能处理100命令。
2、要实现分布式数据库的更大存储量和高并发访问量,我们会将原来集中式数据库的数据分别存储到其他多个网络节点。Redis为了解决这个单一节点问题,也会将数据复制多个副本部署到其他节点上进行复制,实现Redis的高可用,实现数据的冗余备份,从而保证数据和服务的高可用。
Redis复制是高可用的基石。如果没有redis复制也就不可能实现高可用。

为什么不只使用一台redis?

第一,机器故障。我们部署到一台 Redis
服务器,当发生机器故障时,需要迁移到另外一台服务器并且要保证数据是同步的。而数据是最重要的,如果你不在乎,基本上也就不会使用 Redis
了。

第二,容量瓶颈。当我们有需求需要扩容 Redis 内存时,从 16G 的内存升到 64G,单机肯定是满足不了。当然,你可以重新买个 128G
的新机器。

第三,QPS 瓶颈。Redis 号称支持10 万 QPS,当业务需要 100 万 QPS 时,我们该怎么做呢?这时就用到了 Redis 复制

三、复制原理

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

步骤:

步骤 主服务器操作 从服务器操作
1 等待命令进入 连接(或者重连)主服务器,发送SYNC命令
2 开始执行BGSAVE,并使用缓冲区记录BGSAVE之后执行的所有写命令 根据配置选项来决定是继续使用现有的数据(如果有的话)来处理客户端的命令请求,还是向发送请求的客户端返回错误
3 BGSAVE执行完毕,向从服务器发送快照文件,并在发送期间继续使用缓冲区记录被执行的写命令 丢弃所有旧数据(如果有的话),开始载入主服务器发送来的快照文件
4 快照文件发送完毕,开始向从服务器发送存储在缓冲区里面的写命令 完成对快照文件的解释操作,向往常一样开始接受命令请求
5 缓冲区存储的写命令发送完毕,从现在开始,每执行一个写命令,就像从服务器发送相同的写命令 执行主服务器发送来的所有存储在缓冲区里面的写命令,并从现在开始,接收并执行主服务器传来的每个命令
全量复制与部分复制

1、全量复制

在这里插入图片描述

第一步,Redis 内部会发出一个同步命令,刚开始是 Psync 命令,Psync ? -1 表示要求 Master 主机同步数据;

第二步,Master 会向从机发送 runid 和 offset,因为 Slave 并没有对应的 offset,所以是全量复制;

第三步,通过指令 save masterInfo,从机 Slave 会保存 Master 的基本信息;

第四步,Master 执行 bgsave 命令(持久化命令),对于一个快照来说,怎么快怎么来。实际上 Master 主机里有
repl_back_buffer(复制缓冲区);

第五步,通过指令 send RDB 发送 RDB 文件;

第六步,发送缓冲区数据;

第七步,刷新旧的数据;

第八步,加载 RDB 文件和缓冲区数据的加载。

那么全量复制需要哪些开销呢?

  • bgsave 时间;
  • RDB 文件网络传输时间;
  • 从节点清空数据的时间;
  • 从节点加载 RDB 的时间;
  • AOF 重写的时间(这里需要说明一下,RDB 全量复制完加载 RDB,如果 AOF 开启的话,就会出现 AOF 重写来保证是最新的)。

2、部分复制

部分复制是 Redis 2.8 以后出现的,之所以要加入部分复制,是因为全量复制会产生很多问题,比如像上面的时间开销大、无法隔离等问题,
Redis 希望能够在 Master 出现抖动(相当于断开连接)的时候,可以有一些机制将复制的损失降低到最低。

第一步,如果打算抖动(连接断开 connection lost);

第二步,Master 还是会写 repl_back_buffer(复制缓冲区);

第三步,Slave 会继续尝试连接主机;

第四步,Slave 会把自己当前 runid 和偏移量传输给主机 Master,并且执行 pysnc 命令同步;

第五步,如果 Master 发现你的偏移量在缓冲区的范围内,就会返回 continue 命令;

第六步,同步了 offset 的部分数据,所以部分复制的基础就是偏移量 offset。

通过部分复制,可以有效的减少全量复制的开销。

四、实践操作

为了方便 这里使用一台服务器进行操作,拷贝了3个配置文件,分别是redis6379.conf;redis6380.conf;redis6381.conf.

配从(库)不配主(库)

模拟环境

1、修改配置文件:

1、修改配置文件端口号(6379,6380,6381);port:***

2、开启守护进程 daemonize yes

3、指定不同的pid名称如:pidfile /var/run/redis_6380.pid

4、指定不同的log名如:logfile “redis6380.log”

5、指定不同的dump.rdb如:dbfilename dump6380.rdb

6、指定不同的aof(如果开启的话),如:appendfilename “appendonly6381.aof”

2、启动

以配置文件的方式分别启动三个服务6379,6380,6381

redis-server /usr/local/redis6379.conf
redis-server /usr/local/redis6380.conf
redis-server /usr/local/redis6381.conf

进入redis

redis-cli -p 6379
redis-cli -p 6380
redis-cli -p 6381
常见Redis复制

1、一主二仆

即一个主机两个从机

在这里插入图片描述

这里6379作为我们的主机,6381,6380作为从机。 当Slave与Master断开后需要重新slave
of连接才可建立之前的主从关系;Master挂掉后,Master关系依然存在,Master重启即可恢复。

2、薪火相传

上一个Slave可以是下一个slave的Master,Slave同样可以接收其他slaves的连接和同步请求,那么该slave作为了链条中下一个的master,可以有效减轻master的写压力

中途变更转向:会清除之前的数据,重新建立拷贝最新的

在这里插入图片描述
3、反客为主

当Master挂掉后,Slave可键入命令 slaveof no one使当前redis停止与其他Master redis数据同步,转成Master redis。

五、Redis哨兵机制

反客为主的自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库

哨兵(Sentinel)机制的意义:

Redis复制过程中有一个很大的缺点,当我们的主机宕机过后,需要我们人工去解决,Redis哨兵就是为了解决这个问题。
Redis哨兵是一个分布式的架构,每一个Sentinel节点会对数据节点和其余Sentinel节点进行监控,当发现某个节点无法到达的时候,会自动标识该节点。如果这个节点是主节点,那么他会和其他Sentinel节点‘协商’,大部分节点都认为主节点无法到达的时候,他们会选举一个Sentinel节点来完成自动故障转移,同时告诉Redis应用方。

哨兵(Sentinel)的作用:

监控(Monitoring): 哨兵(sentinel) 会不断地检查你的Master和Slave是否运作正常。

提醒(Notification):当被监控的某个 Redis出现问题时, 哨兵(sentinel) 可以通过 API 向管理员或者其他应用程序发送通知。

自动故障迁移(Automatic failover): 当一个Master不能正常工作时,哨兵(sentinel) 会开始一次自动故障迁移操作,它会将失效Master的其中一个Slave升级为新的Master, 并让失效Master的其他Slave改为复制新的Master; 当客户端试图连接失效的Master时,集群也会向客户端返回新Master的地址,使得集群可以使用Master代替失效Master。

哨兵(Sentinel)工作方式:

1、每个Sentinel(哨兵)进程以每秒钟一次的频率向整个集群中的Master主服务器,Slave从服务器以及其他Sentinel(哨兵)进程发送一个PING 命令。

2、如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被 Sentinel(哨兵)进程标记为主观下线(SDOWN)。

3、如果一个Master主服务器被标记为主观下线(SDOWN),则正在监视这个Master主服务器的所有 Sentinel(哨兵)进程要以每秒一次的频率确认Master主服务器的确进入了主观下线状态。

4、当有足够数量的 Sentinel(哨兵)进程(大于等于配置文件指定的值)在指定的时间范围内确认Master主服务器进入了主观下线状态(SDOWN), 则Master主服务器会被标记为客观下线(ODOWN)。

5、在一般情况下, 每个 Sentinel(哨兵)进程会以每 10 秒一次的频率向集群中的所有Master主服务器、Slave从服务器发送 INFO 命令。

6、当Master主服务器被 Sentinel(哨兵)进程标记为客观下线(ODOWN)时,Sentinel(哨兵)进程向下线的 Master主服务器的所有 Slave从服务器发送 INFO 命令的频率会从 10 秒一次改为每秒一次。

7、若没有足够数量的 Sentinel(哨兵)进程同意 Master主服务器下线, Master主服务器的客观下线状态就会被移除。若 Master主服务器重新向 Sentinel(哨兵)进程发送 PING 命令返回有效回复,Master主服务器的主观下线状态就会被移除。

哨兵(Sentinel)机制实践:

这里我的环境分别为:

134.98.1.72 6379 Master 作为主服务器

134.98.1.80 6379 slave 从服务器 slaveof 134.98.1.72 6379

134.98.1.81 6381 slave 从服务器 slaveof 134.98.1.72 6381

分别启动三台服务器的Redis。可以通过配置文件或者手动的将80,81配置为从服务器。

配置文件主要改动

bind 0.0.0.0

protected-mode no

sentinel.conf文件配置

#
bind 0.0.0.0
#
protected-mode no

# port <sentinel-port>
# The port that this sentinel instance will run on
port 26379 端口号

daemonize no  

pidfile "/var/run/redis-sentinel.pid" 

logfile "/usr/local/log/sentinel.log" 日志地址


sentinel monitor mymaster 134.98.1.72 6379 2 
表示 Sentinel(哨兵)进程去监视一个名为 mymaster 的主服务器,这个主服务器的 IP 地址为 134.98.1.72, 端口号为 6379,而将这个主服务器判断为失效至少需要 2 个 Sentinel(哨兵)进程的同意

sentinel down-after-milliseconds mymaster 5000
 Sentinel(哨兵)进程判断服务器已经掉线所需的毫秒数。


  sentinel parallel-syncs mymaster 1

sentinel failover-timeout mymaster 60000


按照顺序 分别启动Master–>slave–>sentinel

sentinel 启动:redis-sentinel sentinel.conf

启动后:

此时的master是我们的72服务器,80,81为从服务器;

13437:X 23 Apr 2019 16:04:48.053 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
13437:X 23 Apr 2019 16:04:48.053 # Redis version=5.0.4, bits=64, commit=00000000, modified=0, pid=13437, just started
13437:X 23 Apr 2019 16:04:48.053 # Configuration loaded
13437:X 23 Apr 2019 16:04:48.054 * Increased maximum number of open files to 10032 (it was originally set to 1024).
13437:X 23 Apr 2019 16:04:48.055 # Could not create server TCP listening socket 192.168.1.1:26379: bind: Cannot assign requested address
                _._                                                  
           _.-``__ ''-._                                             
      _.-``    `.  `_.  ''-._           Redis 5.0.4 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                   
 (    '      ,       .-`  | `,    )     Running in sentinel mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 26379
 |    `-._   `._    /     _.-'    |     PID: 13437
  `-._    `-._  `-./  _.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |           http://redis.io        
  `-._    `-._`-.__.-'_.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |                                  
  `-._    `-._`-.__.-'_.-'    _.-'                                   
      `-._    `-.__.-'    _.-'                                       
          `-._        _.-'                                           
              `-.__.-'                                               

13437:X 23 Apr 2019 16:04:48.056 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
13437:X 23 Apr 2019 16:04:48.060 # Sentinel ID is 1065cb78d77eabcccbee19b2c2f4585fa08e9390
13437:X 23 Apr 2019 16:04:48.060 # +monitor master mymaster 134.98.1.72 6379 quorum 2
13437:X 23 Apr 2019 16:04:48.061 * +slave slave 134.98.1.81:6379 134.98.1.81 6379 @ mymaster 134.98.1.72 6379
13437:X 23 Apr 2019 16:04:48.063 * +slave slave 134.98.1.80:6380 134.98.1.80 6380 @ mymaster 134.98.1.72 6379
13437:X 23 Apr 2019 16:05:31.929 * +sentinel sentinel 0881a984e2229c92812a37e24dfddfc338caf8d8 134.98.1.81 26379 @ mymaster 134.98.1.72 6379
13437:X 23 Apr 2019 16:06:12.481 * +sentinel sentinel 034d49988aa4f58efbe2db5f6c6c5475d3651ad4 134.98.1.80 26379 @ mymaster 134.98.1.72 6379

我们模拟master宕机,将master shutdown后,sentinel开始工作选举新的slave作为master

13437:X 23 Apr 2019 16:07:36.863 # +sdown master mymaster 134.98.1.72 6379
13437:X 23 Apr 2019 16:07:36.990 # +new-epoch 1
13437:X 23 Apr 2019 16:07:36.992 # +vote-for-leader 0881a984e2229c92812a37e24dfddfc338caf8d8 1
13437:X 23 Apr 2019 16:07:37.988 # +odown master mymaster 134.98.1.72 6379 #quorum 3/2
13437:X 23 Apr 2019 16:07:37.988 # Next failover delay: I will not start a failover before Tue Apr 23 16:09:37 2019
13437:X 23 Apr 2019 16:07:38.070 # +config-update-from sentinel 0881a984e2229c92812a37e24dfddfc338caf8d8 134.98.1.81 26379 @ mymaster 134.98.1.72 6379
13437:X 23 Apr 2019 16:07:38.070 # +switch-master mymaster 134.98.1.72 6379 134.98.1.81 6379
13437:X 23 Apr 2019 16:07:38.070 * +slave slave 134.98.1.80:6380 134.98.1.80 6380 @ mymaster 134.98.1.81 6379
13437:X 23 Apr 2019 16:07:38.070 * +slave slave 134.98.1.72:6379 134.98.1.72 6379 @ mymaster 134.98.1.81 6379
13437:X 23 Apr 2019 16:07:43.145 # +sdown slave 134.98.1.72:6379 134.98.1.72 6379 @ mymaster 134.98.1.81 6379

上面可以看到 81机器已经成功上位 成为新的master,80自动跟从于81主机

通过info replication 查看信息可看到
81机器

# Replication
role:master
connected_slaves:1
slave0:ip=134.98.1.80,port=6380,state=online,offset=1059414,lag=1
master_replid:49c4d69750208186e74d53f6e7d02576cbc67fa6
master_replid2:b754d6583e4c987d8b51fe29f443479397ef8572
master_repl_offset:1059551
second_repl_offset:1050157
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1023219
repl_backlog_histlen:36333

80机器

# Replication
role:slave
master_host:134.98.1.81
master_port:6379
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0
slave_repl_offset:1062593
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:49c4d69750208186e74d53f6e7d02576cbc67fa6
master_replid2:b754d6583e4c987d8b51fe29f443479397ef8572
master_repl_offset:1062593
second_repl_offset:1050157
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1023303
repl_backlog_histlen:39291

问题:如果此时原来的master 72机器恢复好了 重新启动会是什么情况呢?下面我们模拟一下。
启动成功 sentinel日志里看见:
在这里插入图片描述
info replication 查看得知

# Replication
role:slave
master_host:134.98.1.80
master_port:6380
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:1125636
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:49c4d69750208186e74d53f6e7d02576cbc67fa6
master_replid2:b754d6583e4c987d8b51fe29f443479397ef8572
master_repl_offset:1125636
second_repl_offset:1050157
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1050157
repl_backlog_histlen:75480

此时我们的主机依然还是81机器,而原来的主机会自动成为slave跟从于81机器。

哨兵选举算法:

会考虑slave的一些信息:

  1. 跟master断开连接的时长
  2. slave优先级
  3. 复制offset
  4. run id

如果一个slave跟master断开连接已经超过了down-after-milliseconds的10倍,外加master宕机的时长,那么slave就被认为不适合选举为master(down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state

接下来会对slave进行排序(1)按照slave优先级进行排序,slave priority越低,优先级就越高(2)如果slave priority相同,那么看replica offset,哪个slave复制了越多的数据,offset越靠后,优先级就越高(3)如果上面两个条件都相同,那么选择一个run id比较小的那个slav

如果想要slave 永远不参与选举 可以将slave priority设为0

【参考资料】
《Redis实战》
GitChat – Redis入门到分布式实践
https://www.jianshu.com/p/63e2d3e1d9ee
https://www.cnblogs.com/PatrickLiu/p/8444546.html

如有总结不当,有问题,错误的地方请大家予以指正,共同学习,共同进步

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章