Redis 技术内幕——主从同步原理

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/smartbetter/article/details/94388363

单机 Redis 可能存在机器故障、容量瓶颈和 QPS 瓶颈。主从复制为一个数据提供了多个副本,扩展了读性能。一个 Master 可以有多个 Slave,一个 Slave 只能有一个 Master,Redis 数据流向是单向的,Master 到 Slave。

主从同步存在的问题?需要手动故障转移。

1.主从同步实现方式

主从同步有两种实现方式:

1、slaveof 命令实现

在 Slave 上执行 slaveof [master_ip master_port] 命令即可,slaveof 命令是异步的。取消复制只需要在 Slave 上执行 slaveof no one 命令即可,取消复制并不会清除之前复制过的数据。

优点是无需重启,缺点是不便于管理。

2、redis.conf 配置文件实现

在 redis.conf 中添加 slaveof master_ip master_port 配置即可,如果希望 Slave 只读,可以增加 slave-read-only yes 配置。

优点是统一配置,缺点是需要重启。

建议第一次启动可以使用 redis.conf 配置文件实现,后期运维可以考虑使用命令实现。

2.全量同步和增量同步

主从同步主要分为全量同步和增量同步。

全量同步过程:

  • slave 发送 sync 命令到 master;
  • master 启动一个后台进程,将 Redis 中的数据快照保存到文件中(bgsave);
  • master 将保存数据快照期间接收到的写命令缓存起来(AOF);
  • master 完成写文件操作后,将该文件发送给 slave;
  • 使用新的 RDB 文件替换掉旧的 RDB 文件;
  • master 将这期间收集的增量写命令发送给 slave;

增量同步过程:

  • master 接收到用户的操作指令,判断是否需要传播到 slave,增删改需要传播,查不传播;
  • 将操作记录追加到 AOF 文件;
  • 将操作传播到其他 slave:对齐主从库;往响应缓存写入指令;
  • 将缓存中的数据发送给 slave。

两个概念:

runid:Redis 每次启动的时候都会有一个随机 ID 作为 Redis 的标识,重启之后会发生变化。
offset:复制偏移量。在 master 和 slave 中都会有 offset。master 传输出去 N 个字节,master 的 offset 增加 N;slave 收到 N 个字节,slave 的 offset 增加 N。

全量复制原理:

首先将 master 本身的 RDB 文件同步给 slave,而在同步期间,master 写入的命令也会记录下来(master 内部有一个复制缓冲区,会记录同步时 master 新增的写入),当 slave 将 RDB 加载完后,会通过偏移量的对比将这期间 master 写入的值同步给 slave。

为什么要增量复制?

在 Redis 2.8 版本之前,如果 master 和 slave 之间的网络发生了抖动连接断开,就会导致 slave 完全不知道 master 的动作,同步就会出问题,而为了保证数据一致,等网络恢复后进行一次全量复制。而全量复制的开销是很大的,Redis 2.8 版本就提供了一个增量复制的功能。

增量复制的实现原理:

当 master 和 slave 断开连接时,master 会将期间所做的操作记录到复制缓存区当中(可以看成是一个队列,其大小默认 1M)。待 slave 重连后,slave 会向 master 发送 psync 命令并传入 offset 和 runId,这时候,如果 master 发现 slave 传输的偏移量的值,在缓存区队列范围中,就会将从 offset 开始到队列结束的数据传给 slave,从而达到同步,降低了使用全量复制的开销。

3.故障处理

主从复制中处理故障转移分为 slave 宕掉和 master 宕掉两种情况。

slave 宕掉故障处理:

slave 宕掉后,对于 master 无影响,只是对 slave 有影响,一般来说会将 宕掉 slave 的流量切到正常的 slave 节点上。

master 宕掉故障处理:

master 宕掉后,相对比较麻烦,master 读写节点是无法对外提供服务的,slave 只读节点是无影响的,最常见的方案就是将一个 slave 切为 master,选择一个 slave 节点执行 slaveof no one 命令让它成为一个 master,然后对其余的 slave 执行 slaveof new master 命令。

也可以看出,主从复制这个模型没有实现真正的自动故障转移(一个服务挂掉了,另一个服务可以自动顶上来,把故障自动转移掉)。Redis 自动故障转移提供了 Redis Sentinel。Redis Sentinel 见。

4.常见问题

1、读写分离问题

读流量分摊到从节点。可能遇到的问题:复制数据延迟;读到过期数据;从节点故障。

2、配置不一致问题

例如 maxmemory 不一致,会导致丢失数据;
例如数据结构优化参数 hash-max-ziplist-entries 不一致,会导致内存不一致。

3、规避全量复制

第一个场景:第一次全量复制。

第一次挂 slave 节点不可避免。

第二个场景:节点运行 ID 不匹配。

主节点重启(runid 变化)。可以采用故障转移的方式避免,例如哨兵或集群。

第三个场景:复制积压缓冲区不足。

默认值 1MB,例如网络中断,部分复制无法满足则会进行全量复制。可以通过增大复制缓冲区配置 rel_backlog_size 避免。

4、规避复制风暴

单节点复制风暴:

问题:主节点重启,多从节点复制

解决:更换复制拓扑。master -> slave 变为 master -> slave-1 -> slave-1-a 。

单机器复制风暴:

问题:机器宕机后,大量全量复制。

解决:主节点分散多机器。

展开阅读全文

没有更多推荐了,返回首页