06.主从库数据一致
我们学习了AOF和RDB,如果Redis出现了宕机的情况,可以分别通过回访日志和重新读入RDB文件进行恢复数据,保证少的丢失数据,提高可靠性
不过,在实际使用过程中,如果Redis出现了宕机,在恢复过程中,是无法提供服务的
那么为了避免中断问题,提高服务的冗余量,可以将一个数据同时保存在多个实例中,如果有一个实例出现了故障,需要过一段时间才能恢复,但其他的实例并不会被影响
Redis对于上述的多实例保存的实现,就利用了主从库模式,来保证数据副本的高可用
读操作,是主库和从库都可以接受的
写操作,只有主库执行
为了避免数据的不一致,所以仅支持主库接受写请求
而我们主要调查和学习的方向,是关于主从库同步过程
首先,我们需要看一下主从库的第一次同步是如何进行的
我们在启动多个Redis的时候,可以使用replicaof来形成主从库的关系,比如有两个实例 A:172.16.19.3 B:172:16.19.5,执行如下的命令
replicaof 172.16.19.3 6379
这样B就成为A的从库了,接下来B和A要进行第一次的同步
首先是从库发送建立连接的请求,建立了长连接,从而方便发送同步命令
首先从库给主库发送psync命令,表明要进行数据同步,pysnc包含了主库的runID和复制进度offset两个参数
runID,每个Reids实例启动的时候自动生成一个随机ID,用来随机表示这个实例,第一次复制的时候,runID为?
offset,这时候设置为-1 表示第一次复制
然后主库发送一个ACK,一个FULLRESYNC相应,表示第一次复制采用的全量复制,FULLRESYNC带上了主库的runID和主库当前的复制进度offset,返回给从库,从库收到响应后,记录下这两个参数,方便下次同步直接拉去
然后主库生成一个RDB文件,执行bgsave命令来进行生成,然后发给从库在收到RDB文件后,后清空当前的数据库,然后重新加载RDB文件,这是为了避免之前数据的影响,从库需要先将数据库清空
最后为了避免主从在传递RDB文件的时候,主库新收到的数据无法同步给从库,主库内存中记录了专门的replication buffer,在发送完成RDB之后,将replication buffer中的操作也发给从库
然后在主从复制的过程中,如果全部的从库都连接到主库上的话,主库为了维护和从库的网络连接,以及传输RDB,会造成不小的负担,所以Redis还支持了主从从的模式
就是将一个从库作为二级主库,负责级联其他的从库,也是使用 replicaof 所选从库IP 6379
这样就可以减少主库的压力
在主从库之间,利用一个长连接来及数据的操作和同步
不过如果网络出现了问题和断链,那么就需要考虑重新连接后的数据同步问题
如果是简单的解决方案,可以考虑在出现了网络问题之后,主从库之间就重新进行一次全量复制,开销不小
而在Redis中,则是利用了一个repl_backlog_buffer的缓冲区,来保证主从库之间的数据同步
在这个缓冲区中,是一个环形缓冲区,主库在其中记录自己小大的位置,从库记录自己读到的位置
一开始的时候,主从的位置在一起,是其起始位置,随着主库不断接收新的写操作,写操作会增加偏移量,而从库则不断的往主库的偏移量上靠拢,所以一般情况下两者偏移量基本相等
主从库的连接恢复后,从库会给主库发psync命令,将自己当前的slave_repl_offset发给主库,
然后主库判断自己的master_repl_offset和slave_repl_offset之间的差距
然后根据差距来走不同的流程
如果在repl_backlog_buffer的范围区间之内,那么主库直接同步给从库就可以了
但由于repl_backlog_buffer是一个环形数组,类似redo log buffer,在缓冲区写满的时候,主库继续写入,会覆盖掉之前的写入操作,这种时候,如果slave_repl_offset的小于最小的缓冲,那么就只能考虑RDB全量复制了
为了避免过多的RDB复制,可以考虑调整repl_backlog_size,这个参数和所需的缓冲空间有关,缓冲空间的计算方式为 主库写入速度 * 操作大小 – 主从间的网络传输速度 * 操作大小
一般最后再乘以2,获得repl_backlog_size的最终值
一般,每秒写入2000个操作,每个操作大小为2KB,这样就需要2MB的缓冲空间, 然后乘以2,最终设置为4MB
那么总结一下本节学习,主要是关于Redis的主从库的同步原理,有三种模式,全量复制,基于长连接的命令传播,以及增量复制
全量复制是供第一次同步使用的,对于此,建议一个Redis实例的数据库不要太大,在几GB级别比较合适,减少RDB文件生成,传输和重新加载的开销,为了避免多个从库同时和主库进行全量复制,还可以采用 主-从-从的模式,减少主库的压力
最后就是增量复制过程中,repl_backlog_size这个配置参数,如果配置的小,那么就可能导致从库的复制进度赶不上主库,导致从库进行全量备份,可以考虑对应增大参数
最后一个问题,RDB和AOF记录相比,AOF的操作命令更全,为何不考虑使用AOF呢?
在说到repl_backlog_size的时候,就联想到了redo_log_buffer,
对于AOF为何没有采用,AOF文件就因为保存的完整,所以体积更大,不适合传输,而且读取更加缓慢,不如二进制的RDB文件