Redis主从架构
主从集群,实现读写分离
主从数据同步
主从同步流程
- slave节点向master节点发送replicaof命令建立连接,随后发送 psync {repID} {offset} 指令,repID表示主节点唯一标识,offset为复制偏移量。如果是第一次同步,那么repID是?,offset是-1。即psync ? -1
- master节点收到了psync命令后,会响应slave节点并发送 fullresync {repID} {offset} 指令,slave节点会把repID和offset保存下来
- master收到 psync {repID} {offset} 指令后,会执行 bgsave 异步命令生成RDB文件,然后把RBD文件发送给slave节点,slave节点收到RDB文件后,会清空内存数据并加载RDB文件到内存中。
- master节点生成RDB文件时是异步的,此时master节点是非阻塞的,所以在master节点生成RDB文件,发送RBD文件以及slave节点加载RDB文件的过程中,master节点的写命令会放到缓冲区replication_buffer中,在slave节点加载完RDB文件后,主节点会将replication_buffer的内容发送到slave节点,slave节点会执行replication_buffer中的指令,从而达到主从数据一致。
- 如果从节点与主节点发生网络断连,在从节点再次连接后,主节点收到PSYNC命令,会检查从节点提供的repID和offset。
- 如果repID匹配且offset之后有新的写命令记录,则主节点选择进行增量同步。主节点会从复制积压缓冲区(repl_backlog_buffer)中找出从节点缺失的命令日志,并将这些日志发送给从节点。从节点接收到命令后更新内存数据,达到与主节点一致的状态。
- 如果从节点提供的repID与主节点不匹配,或者offset超出了主节点复制积压缓冲区的范围,此时会进行全量同步
注意:
1、如果master节点传输RDB文件以及slave节点加载RDB文件耗时过长,同时master节点接收的写命令过多,导致replication_buffer复制缓冲区写满被溢出,那么master节点会关闭与slave节点的连接,此时replication_buffer的数据会被清空,然后重新开始全量同步。所以replication_buffer大小需要设置一个合理的值。
2、在主从进行全量rdb后,master会把rdb通信期间收到的新的写命令写入replication_buffer,同时也会把写入rep_backlog_buffer复制积压缓冲区。在从节点与主节点断连的时间中,主节点如果有写命令,会把写入到repl_backlog_buffer缓冲区,如果断连时间过长repl_backlog_buffer可能会被写满,新的命令覆盖掉了旧数据。此时从节点会进行全量复制。(是否全量同步是根据 repId 或 offset 参数去判断)
replication_buffer(复制缓冲区)
通过 client-output-buffer-limit slave 参数设置,当这个值太小会导致主从复制连接断开,master会频繁bgsave生成RDB全量同步,影响redis性能。
语法:
client-output-buffer-limit <class> <hard limit> <soft limit> <soft seconds>
class:
Normal:普通的客户端。默认limit 是0,也就是不限制。
Slaves:从库的复制客户端。默认hard limit是256M,soft limit是64M,soft seconds是60s。
Pub/Sub:发布与订阅的客户端的。默认hard limit是32M,soft limit是8M,soft seconds是60s。
hard limit:缓冲区大小的硬性限制。
soft limit:缓冲去大小的软性限制。
soft seconds:缓冲区大小达到了(超过)soft limit值的持续时间。
三种默认配置:
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
repl_backlog_buffer(复制挤压缓冲区)
通过repl_backlog_size参数设置(在redis中的config配置文件中),默认大小是M
大体算法如下:
每秒产生的命令 乘以((master执行rdb bgsave的时间)+ (master发送rdb到slave的时间) + (slave load rdb文件的时间) ) ,来估算积压缓冲区的大小,repl-backlog-size 值不小于这两者的乘积。
例:
如果主服务器平均每秒产生1 MB的写数据,而从服务器断线之后平均要5秒才能重新连接上主服务器,那么复制积压缓冲区的大小就不能低于5MB。
为了安全起见,可以将复制积压缓冲区的大小设为2*5=10M,这样可以保证绝大部分断线情况都能用增量从而避免全量同步数据。
简述全量同步和增量同步的区别
- 全量同步:master通过bgsave命令异步将完整的内存数据生成一个RDB文件并发送到slave节点。master在生成RDB文件、传输RDB文件以及slave节点加载RDB文件的耗时中,master如果接收到了新的写命令会记录到replication_buffer缓冲区。在slave加载完RDB文件后,再把replication_buffer中的命令再发送到slave节点
- 增量同步:slave节点提交repld和offset,master进行判断符合条件后,根据offset偏移量把replication_buffer缓存区中的未发送的命令发送到slave节点
什么时候执行全量同步
- slave节点第一次请求数据同步时
- replication_buffer缓存被覆盖时
- slave节点与master节点发生网络断连,且offset不在repl_backlog_buffer缓冲区范围内
什么时候执行增量同步
- slave节点断开又恢复,且offset在repl_backlog_buffer缓冲区范围内