您的位置:首页 > 数据库 > Redis

Redis 技术内幕——Redis 主从复制原理

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

单机 Redis 可能存在机器故障、容量瓶颈和 QPS 瓶颈。主从复制为一个数据提供了多个副本,扩展了读性能(读写分离)。

Redis 主从复制:

  • 一个 master 可以有多个 slave;
  • 一个 slave 只能有一个 master;
  • 数据流向是单向的,master 到 slave。

1.主从复制配置

主从复制有两种实现方式,slaveof 命令实现和配置文件实现。

1.命令实现

在 slave 上执行 slaveof [master_ip master_port] 命令即可,slaveof 命令是异步的。

取消复制:在 slave 上执行 slaveof no one 命令即可,取消复制并不会清除之前复制过的数据。

2.配置文件实现

在 Redis 启动之前,在 redis.conf 中添加 slaveof master_ip master_port 配置,如果希望 slave 节点只做读操作,可以再增加 slave-read-only yes 配置。

方式 命令实现 配置文件实现
优点 无需重启 统一配置
缺点 不便于管理 需要重启

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

2.全量复制和部分复制

两个概念:

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 。

单机器复制风暴:

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

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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: