Redis是如何保证数据一致性的
前言
说到Redis的高可靠性,我们很容易想到AOF或者RDB快照,它们通过日志文件的方式恢复数据。但是宕机期间,我们的服务就会受到影响。
巴菲特曾说过:不要把鸡蛋都放在一个篮子里。这句话的含义就是要将风险分散开来,在Redis的高可靠性保证来说也是一样。我们不能只把数据都放在一台服务器上,需要将数据复制在多台实例上,这样就能在一台服务器故障时,依然有其他的服务器工作,这就是今天要将的Redis主从同步。
主从库模式的工作方式
主从库之间是采用读写分离的方式:
- 读操作:主从库都可以接收;
- 写操作:只有主库能执行,主库写完后再同步给从库。
为何写操作只能在主库执行呢?这是因为如果写操作可以在任一库中执行,同一份数据多次更新后就会产生数据不一致的问题了。接下来说说主从同步的模式。
主从同步有3种工作模式,分别是:
- 全量复制:第一次同步时执行
- 基于长连接的命令传播:主从库正常运行的时候执行
- 增量复制:遇到网络故障时执行。
主从第一次同步
这个过程主要有2部分数据要同步,分别是:
- 当前时刻所有的日志数据;
- 同步阶段新产生的数据。
对于这2部分数据,Redis是用下面3个阶段去完成数据同步的:
- 第一阶段:主从库之间建立连接,从库向主从发出pysync命令,命令包含了主库的运行ID(runID)和复制进度偏移量(offset)参数。
- 第二阶段:主库将此时的所有数据同步到从库,从库收到后,在实例上将数据复制加载。在这个过程中,主库不会被阻塞。同时,这个过程中如果有新的数据产生,主库会在内存用一个叫做replication buffer的结构记录RDB文件生成后收到的写操作。
- 第三阶段:此阶段就是将主库replication buffer新收到的写命令发给从库,从库再去同步这些数据。
对于这个同步过程,主库有2个很耗时的动作:生成RDB文件、传输RDB文件。如果从库很多,全部由主库将全量数据同步到从库,就会导致主库一直在fork子进程的动作中,而fork动作会阻塞主线程处理正常的请求。
此时我们可以采用”主-从-从“的同步模式,就是选择一个从库作为联接主库和其他从库的对象,避免主库忙于处理fork子进程。选择从库的命令就是:
replicaof 从库IP 端口
这个"主-从-从"模式的示意图如下:
当主从库完成了全量复制时,这个主从集群就会有一个长连接去做同步数据的工作,这样可以避免频繁地建立连接产生开销。
增量复制的过程
当网络故障后,主从库就会采用增量复制的方式继续同步数据。
主要过程就是当主从库断开连接后,主库会将这个断连过程中的写操作命令,都写入到一个环形扇区replication buffer,同时也会将命令写到repl_backlog_buffer缓冲区。repl_backlog_buffer这个缓冲区就记录着主库写到的位置,而从库会记录自己读到的位置。
正常情况下,从库在缓冲区的读位置和主库的写位置的偏移量基本相等。主从库连接恢复后, 主库只用把 master_repl_offset 和 slave_repl_offset 之间的命令操作同步给从库就行。
在网络断开期间,若主库的 repl_backlog_size环形缓冲区写满之后,会覆盖数据。连接恢复后,从库通过psync命令将自己记录的slave_repl_offset发给主库。若主库查询不到就进行全量复制,查得到就增量复制。
小结
主从同步过程,主要是增量复制这块较难理解,大家可以参考官方文档多了解一下具体实现。总的来说,主从同步保证了我们实例故障时,Redis尽可能的减少中断的时间。
- 点赞
- 收藏
- 关注作者
评论(0)