redis 主从同步原理
1.为什么需要主从同步
在使用redis服务的时候如果时单机服务,一旦单机服务宕机了,那么可能导致我们整个系统处于不可用状态,或者当系统的访问量大了以后单机的redis服务成功了整个系统的瓶颈,这时候就到了主从复制展示伸手的时候了.主从复制可以帮我们完成以下功能.
1.1 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
1.2 故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
1.3 负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
1.4 高可用基石:主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。
2.相关配置
1.replicaof
在5.0之前redis可以通过在从服务器上执行slaveof ip port来执行主服务器,在5.0之后可以通过replicaof ip port来指定主服务器.
2.slave-read-only
redis的主从只能是主服务器的写命令同步到从服务器,而不能反过来,所以为了保证数据一致性,从服务器只能接收读请求,而不接收写和修改请求.redis提供了slave-read-only参数进行控制,
3.min-slaves-to-write
当一个主服务器有多个从服务器的时候,为了保证数据的可靠性,需要在有超过n个从服务器的时候才允许主服务器执行写操作命令.为此redis提供了min-slaves-to-write参数进行控制,min-slaves-max-lag来确定从服务器的延迟
4.client-output-buffer-limit
设置生成rdb文件的时候缓冲区(replication_buffer)的大小
语法:client-output-buffer-limit <class> <hard limit> <soft limit> <soft seconds>
class可选值有三个,Normal,Slaves和Pub/Sub;hard limit: 缓冲区大小的硬性限制。soft limit: 缓冲去大小的软性限制。soft seconds: 缓冲区大小达到了(超过)soft limit值的持续时间。
5.repl-backlog-size
设置增量同步的时候写命令缓冲区(repl_backlog_buffer)的大小
3.原理分析
3.1 主从同步流程
3.1.1.建立连接
a).当从库执行了replicaof ip port命令之后从服务器保存主服务器的ip和porti信息,
b).从服务器和主服务器建立socket连接,
c).从服务器发送ping命令,并且接收主服务器的pong命令,如果没有接收到pong命令则从新建立连接
d).如果主服务器设置了访问密码则进行权限校验,如果权限校验通过则开始进行数据同步
2.确定同步方式
a).从服务器发送psync runid offset命令到主服务器,第一次同步的时候由于还没有主服务器的runid,所以使用?代替
b).主服务器收到psync命令之后首先判断runid是否和自己的runid一致,如果不一致或者为?,则进行全量同步,主服务器返回给从服务器fullresync响应,如果runid和主服务器一致则判断offset是否还在repl-backlong_buffer缓冲区的范围内,如果不在该缓冲区的范围内了,则进行全量同步,主服务器返回给从服务器fullresync响应,如果在缓冲区范围内则进行增量同步,主服务器返回给从服务器continue响应.如果主服务器详情的是fullresync则还会带上当前服务器runid和目前主库的复制进度offset
3.2 全量同步
当主服务器响应给从服务器fullresync响应之后,主服务器开始执行bgsave命令,生成RDB文件,并且在rdb文件生成完之后会把整个rdb文件发送给从服务器,从服务器接收到rdb文件之后会清空自己的数据库,然后把rdb文件读取到自己的数据库中.由于主服务器在生成rdb文件的时候是不阻塞的,主服务器还可以继续向外提供服务,这时候为了保证主从服务器的数据一致性,主服务器需要把从开始执行bgsave命令到发送rdb文件到从服务器和从服务器把rdb文件恢复到内存中这段时候的所有写命令保存下来然后发给从服务器执行,保存这些写命令的空间就是replication_buffer.他是专门用来保存主服务器在生成rdb文件的时候的写命令的.
如果在主服务器生成rbd到从服务器根据rdb文件把数据恢复到内存中这段时间产生的写命令太多导致replication_buffer保存不了会导致主服务器主动断开主从连接,主服务器会释放掉相关数据,这时候会重新开始主从复制.如果replication_buffer太小会导致这个过程无限循环.所以推荐把replication_buffer设置的大一些,防止出现这种情况
3.3 增量同步
当全量同步完成之后,由于从服务器已经拿到了主服务器的runid和offset,这时候主从服务器之间开始进行增量复制.增量复制的时候主服务器并不是同步的把所有的写命令直接发送给从服务器而是把写命令缓存到一个交repl_backlog_buffer的空间中,然后集中把写命令和offset发送给从服务器,从服务器在接收到命令执行完成之后会把执行了的命令的offset发送给主服务器,这样主服务器可以根据从服务器返回的offset判断哪些命令还没有执行,然后决定下次发送给从服务器的命令和offset.
repl_backlog_buffer是一个环形空间,时间久了新写入的数据会把之前写入的数据覆盖掉,如果从服务器返回的offset不在这个环形空间中,则主服务器会判定数据不一致,然后触发一次全量同步.
repl_backlog_buffer还用在了当主从服务器之间断开连接重新连接之后,从服务器发送psync命令,并且带了runid和offset参数,如果主服务器返现offset还在环形空间中,则不会进行全量服务,而是返回continue继续增量复制.
3.4无盘复制
通常来讲,一个完全重新同步需要在磁盘上创建一个RDB文件,然后加载这个文件以便为从服务器发送数据。如果使用比较低速的磁盘,这种操作会给主服务器带来较大的压力。特别是当系统正在进行 AOF 的 fsync 操作时如果发生快照,fsync 将会被推迟执行,这就会严重影响主节点的服务效率。所以从 Redis 2.8.18 版开始支持无盘复制。所谓无盘复制是指主服务器直接通过套接字将快照内容发送到从节点,生成快照是一个遍历的过程,主节点会一边遍历内存,一遍将序列化的内容发送到从节点,从节点还是跟之前一样,先将接收到的内容存储到磁盘文件中,再进行一次性加载。
posted on 2022-04-12 22:18 monkeydai 阅读(1263) 评论(0) 编辑 收藏 举报