Redis的主从库如何实现数据一致
Redis在宕机后可以使用RDB快照和AOF日志两种方式恢复数据,但是恢复总是需要时间的。所以我们有了主从库,通过数据冗余来实现一台机器宕机,另外一台机器接力接受请求。也就是增加Redis实例
在进行保持数据一致性之前,首先要知道主从库之间是读写分离的。
读操作:主库、从库都可以接收;
写操作:首先到主库执行,然后,主库将写操作同步给从库。
如果我们没有读写分离,对于写操作,我们可以在任意服务器上进行写操作,但不同机器上的数据需要保持数据的一致性,以便接下来被分配的请求到任意服务器上进行读或者写都能实现,写在不同机器上,则要们需要保持数据一致,这是比较困难的。相比之下,我们把写这个动作都落在主库上的话,主库有了最新的数据后,会同步给从库。这样的处理方式,比起之前可以写在任意库上要更简单实现一些。
主从库间进行第一次同步
当我们启动多个 Redis 实例的时候,它们相互之间就可以通过 replicaof(Redis 5.0 之前使用 slaveof)命令形成主库和从库的关系,之后会按照三个阶段完成数据的第一次同步。
如下图:replicaof 172.16.19.3 6379
第一阶段是主从库间建立连接、协商同步的过程,主要是为全量复制做准备。在这一步,从库和主库建立起连接,并告诉主库即将进行同步,主库确认回复后,主从库间就可以开始同步了。
第二阶段,主库将所有数据同步给从库。从库收到数据后,在本地完成数据加载。这个过程依赖于内存快照生成的 RDB 文件。
第三个阶段,主库会把第二阶段执行过程中新收到的写命令,再发送给从库。具体的操作是,当主库完成 RDB 文件发送后,就会把此时 replication buffer 中的修改操作发给从库,从库再重新执行这些操作。
这样一来,主从库第一次同步就实现了。
主从级联模式分担全量复制时的主库压力
通过分析主从库间第一次数据同步的过程,可以看到,一次全量复制中,对于主库来说,需要完成两个耗时的操作:生成 RDB 文件和传输 RDB 文件。
如果从库数量很多,而且都要和主库进行全量复制的话,就会导致主库忙于 fork 子进程生成 RDB 文件,进行数据全量同步。fork 这个操作会阻塞主线程处理正常请求,从而导致主库响应应用程序的请求速度变慢。此外,传输 RDB 文件也会占用主库的网络带宽,同样会给主库的资源使用带来压力。
这是可以用“主 - 从 - 从”模式。通过“主 - 从 - 从”模式将主库生成 RDB 和传输 RDB 的压力,以级联的方式分散到从库上。
简单来说,我们在部署主从集群的时候,可以手动选择一个从库(比如选择内存资源配置较高的从库),用于级联其他的从库。然后,我们可以再选择一些从库(例如三分之一的从库),在这些从库上执行如下命令,让它们和刚才所选的从库,建立起主从关系
从库的从库,选择刚刚所选的从库作为主库replicaof 所选从库的IP 6379
那么,一旦主从库完成了全量复制,它们之间就会一直维护一个网络连接,主库会通过这个连接将后续陆续收到的命令操作再同步给从库,这个过程也称为基于长连接的命令传播,可以避免频繁建立连接的开销。
主从库间网络断了如何解决
从 Redis 2.8 开始,网络断了之后,主从库会采用增量复制的方式继续同步。听名字大概就可以猜到它和全量复制的不同:全量复制是同步所有数据,而增量复制只会把主从库网络断连期间主库收到的命令,同步给从库。