前言
关于Reids的主从复制我们需要掌握如下的核心知识
- 1.如何搭建Redis主从架构
- 2.主从同步期间,如果出现了网络中断,那么重连后主从库同步会是怎样
- 3.主从同步的原理
- 4.主从同步的优缺点?
主从模式简介
主从复制模式,部署多台redis节点,其中只有一台节点是主节(master)点,其他的节点都是从节点(salve),只有 master节点提供数据的事务性操作,slave节点提供读操作。所有slave节点的数据都是从master节点同步过来的。其模式的架构图如下:
主从模式搭建
准备两台Redis服务器
登录从Redis服务,修改redis.conf文件
replicaof 127.0.0.1 6379
masterauth 1234
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
说明:
- replicaof:设置Reids主库的ip和端口,如果是3.0之前版本的采用的是slaveof命令。
- masterauth:设置主从配置的密码
- slave-read-only:从机只开启只读模式默认为yes
- repl-diskless-sync:设置主从同步复制数据的方式,目前主从复制提供了量中方式disk和socket。 disk方式是master创建一个新的进程把rdb文件保存到磁盘,再把磁盘上的rdb文件传递给slave。 socket是master创建一个新的进程,直接把rdb文件以socket的方式发给slave。 disk方式的时候,当一个rdb保存的过程中,多个slave都能共享这个rdb文件。 socket的方式就的一个个slave顺序复制。在磁盘速度缓慢,网速快的情况下推荐用socket方式。
- repl-diskless-sync-delay:diskless复制的延迟时间,防止设置为0。一旦复制开始,节点不会再接收新slave的复制请求直到下一个rdb传输。
- repl-disable-tcp-nodelay:如果master设置了yes来禁止tcp nodelay设置,在把数据复制给slave的时候,会减少包的数量和更小的网络带宽。但是这也可能带来数据的延迟。默认我们推荐更小的延迟,但是在数据量传输很大的场景下,建议选择yes。
配置完成,查看主从的信息
登录从reids服务器,执行如下命令,显示如下信息,则表示Reids主从搭建成功
127.0.0.1:6379> info replication
说明:显示为从库的相关节点信息。
测试数据同步
说明:在主节点设置值,从节点获取值。
原理
主从复制,是主节点产生一份数据的快照发送给从节点,以快照数据为基准,将之后增量的数据变更同步给从节点,从而能保证主从数据的一致。
主从复制的方式
Redis主从同步的方式为:全量复制、增量复制
全量复制
全量复制在Redis的主从第一次建立连接时采用的是全量复制,它会把主节点全部数据一次性发送给从节点,当数据量较大时,会对主从节点和网络造成很大的开销。
全量复制的流程
全量复制的流程大致可以分为三个阶段
- 主从建立连接
- 主从开始库同步数据
- 发送新写命令到从库
详细的流程如下:
第一阶段主从建立连接
第一阶段的作用在于主从节点之间建立连接,为数据全量同步做好准备,从库执行replicaof并发送psync命令并告诉主库即将进行同步,主库收到从库的psync命令后会用FULLRESYNC响应命令进行回复,此命令中包含了主库的runID和offset两个参数,从库收到响应后会记录这个两个参数的值。
- runID:每个Redis实例启动都会自动生成一个唯一标识ID
- offset:第一次复制设置为 -1,表示第一次复制,记录复制进度偏移量。
- FULLRESYNC响应表示第一次复制采用的全量复制,也就是说,主库会把当前所有的数据都复制给从库。
第二阶段主从库同步数据
主库执行bgsave命令生成 RDB文件,并将RDB文件发送给从库,同时主库为每一个slave开辟一块 replication buffer缓冲区记录从生成 RDB文件开始收到的所有写命令。从库收到RDB文件后保存到磁盘,并清空当前数据库的数据,重新加载RDB文件数据到内存中。
第三阶段发送新写命令到从库
从节点加载RDB完成后,主节点将replication buffer缓冲区的数据发送给从节点,从节点接收并执行,从节点同步至主节点相同的状态。
增量复制
Redis2.8开始,网络中断之后,重新连接主从库会采用增量复制的方式继续同步。增量同步主要用于网络中断等情况,只是将中断期间主节点执行的写命令发送给从节点。
基本流程
-
当主从库断连后,主库会把断连期间收到的写操作命令写入replication buffer,同时也会把这些操作命令也写入repl_backlog_buffer这个缓冲区。repl_backlog_buffer是一个环形缓冲区,主库会记录自己写到的位置,从库则会记录自己已经读到的位置。
-
主从库的连接恢复之后,从库首先会给主库发送psync命令,并把自己当前的slave_repl_offset发给主库,主库会判断自己的 master_repl_offset和slave_repl_offset 之间的差距。
-
在网络断连阶段,主库可能会收到新的写操作命令,一般来说master_repl_offset会大于slave_repl_offset。此时主库只用把 master_repl_offset和slave_repl_offset之间的命令操作同步给从库。
特殊说明:repl_backlog_buffer是一个环形缓冲区,所以在缓冲区写满后,主库会继续写入,此时就会覆盖掉之前写入的操作。如果从库的读取速度比较慢,可能会导致从库还未读取的操作被主库新写的操作覆盖了,从而导致主从库数据不一致。
如何避免缓冲区被覆盖
缓冲空间的计算公式为:缓冲空间大小 = 主库写入命令速度 * 操作大小 - 主从库间网络传输命令速度 * 操作大小。在实际应用中,考虑到可能存在一些突发的请求压力,我们通常需要把这个缓冲空间扩大一倍,即 repl_backlog_size = 缓冲空间大小 * 2。
举个例子,如果主库每秒写入1000个操作,每个操作的大小为2KB,网络每秒能传输500个操作,那么有500个操作需要缓冲起来,至少需要1MB的缓冲空间。否则新写的命令就会覆盖掉旧操作了。为了应对可能的突发压力问题,我们最终把repl_backlog_size设为2MB。
优缺点
优点
- 数据备份:同样的数据在多个节点进行存储,起到了备份数据的作用。
- 故障恢复:当master节点发生故障后,可以选择一个slave节点作为master节点提供服务。
- 读写分离:写的操作由master完成,读的操作由slave完成,从而提高性能。
缺点
- 主节点出现故障,需要手动将一个从节点晋升为主节点,同时需要修改应用方的主节点地址,还 需要命令其他从节点去复制新的主节点,整个过程都需要人工干预。
- 主节点的写能力受到单机的限制。
- 主节点的存储能力受到单机的限制。
优化建议
Reids单节点内存大小尽量控制在2~4G作用,如果数据量过大,全量复制阶段主节点fork +保存 RDB文件耗时过大,从节点长时间接收不到数据触发超时,主从节点的数据同步同样可能陷入全量复制->超时导致复制中断->重连->全量复制->超时导致复制中断……的循环。
总结
本文对于Reids的主从复制进行了详细的讲解,主从复制的原理也是其他Reids高可用架构的基础,针对主从复制的优缺点,我们需要结合实际的场景使用。
我正在参与掘金技术社区创作者签约计划招募活动,点击链接报名投稿。