Redis进阶——主从复制:命令演示搭建

前言

一般来说,要将Redis运用于工程中,只使用一台Redis服务是万万不能的,在实际的场景当中单一节点的redis容易面临风险。主要原因有:

  • 结构:单个Redis服务器会发生单点故障,其次一台服务器需处理所有的请求负载,压力较大
  • 容量:单个Redis服务器内存容量有限,就算一台Redis服务器内存容量为256g,也不能将所有内存用作Redis存储内存,通常情况,单台Redis最大使用内存不应该超过20g

如果服务器发生故障,就需要迁移到另外一台服务器上并且还要考虑数据同步问题,另外也存在容量瓶颈现象,当有需求需要扩容Redis内存,就需不断加升内存!

解决办法

通常,我们为了避免服务的单点故障,会把数据复制到多个副本并放在不同的服务器上,且这些拥有数据副本的服务器可以用于处理客户端的读请求,扩展整体的性能!

什么是主从复制?

主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave);数据的复制是单向的,只能由主节点到从节点。

结构图解如下:

解析:采用读写分离。主服务器master可提供读写操作(为了减轻压力通常只处理写请求),当master的数据发生变化,master会发出命令流来保持对salve的数据更新(slave通常提供读)

默认情况下,每台Redis服务器都是主节点;一个master可以有多个slave,即一主多从,但一个从节点只能有一个主节点(爸爸可以有多个孩子,但孩子只有一个亲生父亲!)

★ 主从复制的好处:

  • 数据冗余,实现数据的热备份(另一种持久化模式)
  • 故障恢复,避免单点故障带来的服务不可用(主挂了,从顶上)
  • 负载均衡:配合读写分离,分担负载,主节点负载读写,从节点负责读,提高服务器并发量
  • 高可用基础,是哨兵机制和集群实现的基础

主从复制的配置

如果是真实服务器或多个虚拟机,port 端口号可以一样,但是bind绑定的 IP 地址要不一样!

1、伪造3台服务器

由于条件有限,这里我使用的是伪服务器,用的都是本地服务127.0.0.1,拷贝三份redis.conf 配置文件充当3个服务器,如图:

! ! 注意:大家演示操作的时候,建议默认的配置文件备份一下,恢复默认配置易忘记改动的参数

这里我分别用:6379、6380、6381 三个端口号,redis.conf 配置文件名称也记得区分一下,配置文件中的几个参数需要配置:

# 设置为后台运行
daemonize yes


-- 如果是像我一样一台机器伪造3个服务器,需要命名区分,如果是3台机器则不需要
# 保存pid的文件  ————每个conf配置文件对应自己的端口号区分下名称
pidfile /var/run/redis_6380.pid  # 即redis81.conf就命名:redis_6381.pid,以此类推


# 指定日志文件, (命名区分同上)
logfile "6380.log"


# 指定rdb文件的名称 (命名区分同上)
dbfilename dump6380.rdb



-- 如果是三台机器 上述命名可以不区分,但是这里绑定IP就是机器的IP地址
# 绑定的主机地址,这里注释掉,开放ip连接
#bind 127.0.0.1

查看结果:上述三个conf 配置文件参数修改好后,再分别启动3台服务器,查看服务进程结果:


 

2、配置一主二从

上面也讲述过了,默认情况,每台Redis服务器都是主节点,查看节点信息如下:

  • redis-cli -p [端口号]:连接具体端口的客户端
  • info replication:查看复制信息

根据上图所示,每台服务器默认都是主节点,所以只需要配置从机就好了,把6379当主节点,另外63806381 当作从节点,分别在redis80.conf redis81.conf 配置文件中设置参数如下:

########################## REPLICATION(主从复制) ##########################

# 在5.0版本中使用了replicaof代替了slaveof,slaveof还可以继续使用,建议使用replicaof
replicaof <masterip> <masterport>  # 主机的IP、主机的端口



#----------------------------- 其他参数设置 ------------------------------

-- 注意1:如master设置了requirepass密码,slave用此选项指定master认证密码
 # masterauth <master-password>


-- 注意2:作为从服务器,默认情况下是只读的(yes),可以修改成NO,用于写(不建议)。
slave-read-only yes

具体设置:修改 80、81的conf 配置文件参数如下:      一主(79)二从(80、81)    

 设置完毕记得重启所有的服务和重新连接各客户端,再次查看各节点信息:

3、配置完成,测试数据

情况一:主机写入数据,从机读取数据

情况二:从机写入数据

情况三:主机宕机,从机状态如何?

 宕机后的主机,重连服务后,从机状态如何?

  • 主机宕机后,从机读取数据不影响
  • 主机重新连接后,正常运行,写入的新数据也能被从机立刻读取!

情况四:从机宕机,主机和其他从机状态如何?

即使主机在从机宕机期间,写入新数据,从机一旦重启服务后,也能够获取到这部分数据!

思考:为什么从机宕机了,重连后,也能恢复主机在从机宕机期间新产生的数据呢?

主从复制原理

注意:在2.8版本之前只有全量复制,而2.8版本后有全量和增量复制

  • 全量复制将主节点中整个数据文件都发送给从节点(重型操作)
  • 增量复制主和从节点在中断期间,主库所执行的写命令发送给从节点

注意:如中断时间过长,主节点没完全保存中断期间执行的写命令,仍然会使用全量复制

 ▎全量复制如何理解?

从节点宕机后,重连服务后,会自动向master发送一条sync同步命令,master收到命令后,收集所有数据集命令,再把整个数据文件传送给slave从机,完成从机的数据同步!

 3个阶段

Redis的主从复制过程大体上分3个阶段:建立连接数据同步命令传播

第一阶段是主从库间建立连接、协商同步的过程

psync 命令包含了主库的 runID 和复制进度 offset 。

  • runID:每个 Redis 实例启动时会自动生成的一个随机 ID,用来唯一标记这个实例。当从库和主库第一次复制时,因为不知道主库的 runID,所以将 runID 设为“?”。
  • offset,此时设为 -1,表示第一次复制。

主库收到 psync 命令后,会用 FULLRESYNC 响应命令带上两个参数:主库 runID 和主库目前的复制进度 offset,返回给从库。从库收到后,记录下这两个参数。

注意:FULLRESYNC 响应表示第一次复制采用的全量复制

从库给主库发送 psync 命令,表示要进行数据同步。主库接收命令后来启动复制。

 

第二阶段,主库将所有数据同步给从库

主库执行 bgsave 命令,开始全量复制,生成 RDB 文件并发给从库。从库接收后,先清空当前数据库,再加载 RDB 文件(避免从库的旧数据与主机发过来的rdb数据文件内容冲突),主库同步给从库数据过程中,不会阻塞,仍然正常接收客户端请求。

在同步数据过程中,由于主库仍可接收客户端写请求,这些新产生的写操作未记录到刚生成的RDB文件中,所以为了保证主从库的数据一致性,主库会记录 RDB 文件生成后收到的所有新写操作。再写入到专门的 replication buffer 缓冲区

第三个阶段,主库发送新写命令给从库 ( 第二阶段同步过程中新收到的写命令)

当主库把RDB 文件传送给从库完毕后,就会把 replication buffer 缓冲区中的数据再发给从库,从库再重新执行这些操作。完成主从库的数据一致性!

 
 Replication_buffer 缓冲区

主库会为每一个连接到自己的客户端创建一个replication buffer,用来发送增量写命令。即从库同步主库的rdb文件阶段,主库新产生的写命令会存入到该缓冲区,等从机完成rdb文件的同步后,主库再把该缓冲区的数据发给从库继续同步,保证主从数据一致性

思考一:如果replication buffer缓冲区写满了怎么办?

答:无论客户端是普通客户端还是从库,会断开其客户端连接,重新尝试全量同步

思考二:如何避免replication buffer缓冲区写满?

答:可以在redis.config文件中配置如下参数:

# 主从复制缓存区,32mb表示缓冲区最大是32mb,8mb 60表示如果60s内写入量超过8mb,就会溢出
client-output-buffer-limit slave 32mb 8mb 60

!! 注意:把缓冲区最大值调大,或把每秒允许的写入量增加,可减小缓冲区溢出的概率。但如果连接redis服务器的客户端越多,对内存的损耗也越大,故控制从节点的数量,也可以控制缓存区对内存的开销。当然也可以控制主节点的写命令接收速率。

思考:第二阶段完成rdb文件的同步后,在开始执行第三阶段的时候,此时断开连接怎么办??

从库完成RDB文件同步后,会继续同步从库的增量写命令。如果同步增量写命令的过程中,主从节点中断连接了,怎么办呢?重新连接后需要再次进行全量同步吗????

答:不一定,此时依赖Repl_backlog_buffer缓冲区,请看下方增量复制详解说明。


 

增量复制如何理解?

在master主节点与slave从节点中断连接期间,主节点所产生的新的写命令,会被发送给重连后的从节点(只是中断期间产生新写命令,而不是复制全部数据给从库)

这就是为什么从机断联了,重连后,也能恢复主机在从机宕机期间新产生的数据

图解如下:


 

Repl_backlog_buffer 环形缓冲区

主库的写命令,除了传给从库后,还会写入repl_backlog_buffer,当主从断开后,重新建立连接,从库会发送之前的那个命令:psync $master_runid $offset

这个时候,主库就会在repl_backlog_buffer中找到offset的位置,把之后的写命令写入replication buffer同步给从库。

目的:解决从库断开后,找到主从差异数据而设立的环形缓冲区,避免全量同步的性能开销

图解:

解析:如上图,主库按顺时针方向写命令,从库建立连接后,还有key3和key4这2个命令没有同步,主库只要把这2个命令同步给从库就行了。主库也会记录一个自己的offset,主库offset 和 从库offset之间的命令就是需要同步的增量命令(即 key3、key4)

注意:

  1. 主库不会给每个从库分配一个repl_backlog_buffer,而是所有从库共享一个
  2. 如果环形缓冲区写满了,继续写入就会覆盖最前面的命令
  3. 从库读取慢,从库发送的offset就找不到了(被主库写命令覆盖),只能进行一次全量同步
  4. 从库断开时间过长,会被主库的写命令覆盖,从库重连后,只能全量复制

redis.conf 配置文件中可设置repl_backlog_size参数的大小,降低从库重连后全量同步的概率



 

关闭持久化时,复制的安全性

在进行主从复制设置时,强烈建议在主服务器上开启持久化,当不能这么做时,例如由于非常慢的磁盘性能而导致的延迟问题,应该配置实例来避免重置后自动重启


为什么不开启持久化的主服务器自动重启非常危险呢

  • 假设A节点是master,并关闭持久化,节点BC节点A复制数据。
  • 一旦A节点发生崩溃,由于具有自动重启系统可以自动重启,但由于关闭了持久化,节点重启后其数据为空
  • 节点B会从 节点A进行复制数据,由于节点A是空数据集,复制后的数据也只是一个空数据集,从而覆盖了它们之前的数据副本

结论:如果数据比较重要,使用了主从复制并关闭了master的持久化,都应禁止实例自动重启

什么是无磁盘复制模式?

Redis 默认是磁盘复制,从2.8.18版本开始尝试支持无磁盘的复制。使用这种设置时,子进程直接将RDB通过网络发送给从服务器,不使用磁盘作为中间存储

无磁盘复制模式master创建一个新进程直接dump RDB到slave的socket,不经过主进程,不经过硬盘。适用于disk较慢,并且网络较快的时候。

  • repl-diskless-sync参数:启动无磁盘复制
  • repl-diskless-sync-delay参数:传输开始的延迟时间(单位:秒)

master等待一个repl-diskless-sync-delay 的秒数,如果没slave来的话,就直接传,后来的得排队等了; 否则就可以一起传。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值