1.主从复制在windows环境下的搭建
1.1 搭建一主两从
复制三份下载好的redis到同一个包redis下,并命名为redis6379,redis6380,redis6381,如图所示:
1556073069(1).png
1.2 修改redis.windows.conf配置文件
- redis6379 中修改redis.windows.conf如下信息:
# Accept connections on the specified port, default is 6379 (IANA #815344).
# If port 0 is specified Redis will not listen on a TCP socket.
port 6379
- redis6380 中修改redis.windows.conf如下信息:
# Accept connections on the specified port, default is 6379 (IANA #815344).
# If port 0 is specified Redis will not listen on a TCP socket.
port 6380
slaveof 127.0.0.1 6379
- redis6381 中修改redis.windows.conf如下信息:
# Accept connections on the specified port, default is 6379 (IANA #815344).
# If port 0 is specified Redis will not listen on a TCP socket.
port 6381
slaveof 127.0.0.1 6379
这样我们就搭建了主服务器:127.0.0.1 6379,从服务器:127.0.0.1 6380,127.0.0.1 6380.
1.3 启动服务器
为了方便,我们写三个脚本来启动服务。如图所示:
1556073323(1).png
- start6379.bat内容如下:
@echo off
title redis6379
cd redis6379
redis-server.exe redis.windows.conf
exit
- start6380.bat内容如下:
@echo off
title redis6380
cd redis6380
redis-server.exe redis.windows.conf
exit
- start6381.bat内容如下:
@echo off
title redis6381
cd redis6381
redis-server.exe redis.windows.conf
exit
启动如下:
master:6379.png
slave:6380.png
slave:6381
1.4 测试
开启各个redis客户端测试:
主服务器:set msg "hello"
如下所示:
D:\company\redis\redis6379>redis-cli -p 6379
127.0.0.1:6379> set msg "hello world"
OK
127.0.0.1:6379>
从服务器获取:get msg
如下所示:
D:\company\redis\redis6380>redis-cli -p 6380
127.0.0.1:6380> get msg
"hello world"
127.0.0.1:6380>
D:\company\redis\redis6381>redis-cli -p 6381
127.0.0.1:6381> get msg
"hello world"
127.0.0.1:6381>
这样搭建主从复制算成功了。接下来我们详细讲解下集群。
2. 主从复制概述
2.1 定义
主从复制:就是一台redis服务器B从另一台redis服务器A复制数据。我们称服务器A为主服务器,B服务器为从服务器。其中,每台从服务器只能有一台主服务器,但是一台主服务器可以有多台从服务器。
数据的复制是单向的,只能由主服务器复制到从服务器。
2.2 作用
-
数据冗余
主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。 -
故障恢复
主从复制消除了单点故障问题,如果主服务器宕机,可以由从服务器提供服务。 -
负载均衡
配合读写分离,主服务器可以作为写操作,而读操作可以由从服务器提供,这样分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
3. 如何使用主从复制
3.1 建立复制
建立复制有三种方式:
-
配置文件
在从服务器的配置文件中加入:slaveof<masterip><masterport> -
启动命令
redis-server启动命令后加入:slaveof<masterip><masterport> -
客户端命令
Redis服务器启动后直接通过客户端执行命令:slaveof<masterip><masterport>,则该Redis实例成为从节点。
3.2 断开复制
通过slaveof<masterip><masterport>命令建立主从复制关系以后,可以通过slaveof no one断开。需要注意的是,从节点断开复制后,不会删除已有的数据,只是不再接受主节点新的数据变化。
4. 主从复制原理
主从复制为三个阶段:
连接建立阶段(即准备阶段)、数据同步阶段、命令传播阶段。
4.1 连接建立阶段
4.2 数据同步阶段
数据同步方式有全量复制和部分复制。
-
全量复制
用于初次复制或其它无法进行部分复制的情况,将主节点中的所有数据都发送给从节点,是一个非常重型的操作。 -
部分复制
用于网络中断等情况后的复制,只将中断期间主节点执行的写命令发送给从节点,与全量复制相比更加高效。需要注意的是,如果网络中断时间过长,造成主节点没有能够完整地保存中断期间执行的写命令,则无法进行部分复制,仍使用全量复制。
4.2.1 全量复制
-
全量复制流程
图片.png
全量复制过程如下:
-
全量复制缺点
- 全量复制需要执行bgsave,fork出子线程进行rdb持久化,消耗内存,IO。
- 复制完之后,从服务器需要删除旧的所有数据并载入RDB文件,这个过程是阻塞的,从服务器不能提供服务。
- 在复制未完成之前,master/slave因为网络问题断开连接,而这个时候,master是无法得知某个命令最终
同步给了多少个slave数据库。但是redis提供了一个配置项来限制只有数据至少同步给多少个slave的时候,master才是可写的:
min-slaves-to-write 3 表示只有当3个或以上的slave连接到master,master才是可写的
min-slaves-max-lag 10 表示允许slave最长失去连接的时间,如果10秒还没收到slave的响应,则master认为该slave已断开。
4.2.2 部分复制
当slave与master断开连接,我们需要提供一种类似断开续传的功能,在断开连接之后的部分复制。
部分复制的实现,依赖于三个重要的概念:
复制偏移量
master在内存中创建一个backlog,master和slave都会保存一个复制偏移量offset,这个偏移量就是每次master如果发送N个字节数据,master的offset就会增加N,如果slave接收到这N个字节数据,并载入。则slave复制偏移量offset增加N。然后redis就通过master和slave的偏移量来判断主从服务器的状态一致性,如果不一致,就需要确定再次复制的位置(就是复制积压缓冲区)。如果master和slave网络连接断掉了,slave会让master从上次的replica offset开始继续复制,但是如果没有找到对应的offset,那么就会执行一次全量同步。
比如我们前面搭建的一主两从的主从复制,这里如果主服务器的offset:900,两个从服务器A,B的分别为:offset:900,offset:900.此时主从服务器状态是一致的。
图片.png
现在主服务器发送100个字节数据,两个从服务器接收了,并载入。这时服务器状态是一致的。
图片.png
但是,现在主服务器发送100个字节数据,从服务器A断线没接收到,我们可以看到主从服务器的offset不一致了,那么在从服务器重启之后,这个数据如何恢复呢?就需要复制积压缓冲区。
复制积压缓冲区
复制积压缓冲区是由主服务器维护的固定长度的先进先出的队列,默认大小为1M。
在命令传播阶段,主节点除了将写命令发送给从节点,还会发送一份给复制积压缓冲区,作为写命令的备份;除了存储写命令,复制积压缓冲区中还存储了其中的每个字节对应的复制偏移量(offset) 。由于复制积压缓冲区定长且先进先出,所以它保存的是主节点最近执行的写命令;时间较早的写命令会被挤出缓冲区。
由于该缓冲区长度固定且有限,因此可以备份的写命令也有限,当主从节点offset的差距过大超过缓冲区长度时,将无法执行部分复制,只能执行全量复制。反过来说,为了提高网络中断时部分复制执行的概率,可以根据需要增大复制积压缓冲区的大小(通过配置repl-backlog-size)来设置;例如如果网络中断的平均时间是60s,而主节点平均每秒产生的写命令(特定协议格式)所占的字节数为100KB,则复制积压缓冲区的平均需求为6MB,保险起见,可以设置为12MB,来保证绝大多数断线情况都可以使用部分复制。
从节点将offset发送给主节点后,主节点根据offset和缓冲区大小决定能否执行部分复制:
-
如果offset偏移量之后的数据,仍然都在复制积压缓冲区里,则执行部分复制;
-
如果offset偏移量之后的数据已不在复制积压缓冲区中(数据已被挤出),则执行全量复制。
图片.png
服务器运行ID
在部分复制时,还需要用到服务器运行ID。就是说,从服务器断开之后重连的那台主服务器还是原来的主服务器吗?
比如,原来的主从复制是这样的:
但是主节点宕机重启之后,Runid会发生变化。就不能执行部分复制。
主服务器在从服务器首次复制时,把自己自动生成40个字符的服务器运行ID发送给从服务器,如果从服务器断开重连的时候,需要把这个服务器运行ID发送给主服务器: -
主服务器需要比较这个服务器运行ID和自身保存的服务器ID是否一致。
-
如果一致,则部分复制。如果不一致,则全量复制。
整个流程如下图所示:
图片.png
4.3 命令传播
数据同步完成,就进入了命令传播阶段,主要是猪服务器将写命令发送给从服务器,从服务器更新数据,从而保证主从数据的一致性。
4.3.2 心跳机制
在命令传播阶段,除了发送写命令,主从节点还维持着心跳机制:PING和REPLCONF ACK。心跳机制对于主从复制的超时判断、数据安全等有作用。
6.1 主--从:PING
在命令传播阶段,主服务器定时发送PING命令到从服务器,为了让从节点进行超时判断。。PING发送的频率由repl-ping-slave-period参数控制,单位是秒,默认值是10s
6.1 从--主:REPLCONF ACK
在命令传播阶段,从节点会向主节点发送REPLCONF ACK命令,频率是每秒1次;命令格式为:REPLCONF ACK{offset},其中offset指从节点保存的复制偏移量。主要有以下三个作用:
- 检测主从服务器之间的网络连接状态
- 检测命令丢失
- 辅助实现min-slave选项
网友评论