Redis 高可用方案——主从复制

Redis 高可用方案之主从复制

今天来学习一下 Redis 的高可用方案中的主从复制。主从复制是指当我们部署了拥有多台 Redis 结点的集群时,为了保证数据的一致性,将主节点的数据复制到从节点上的过程。

主从复制主要的目的是:

  • 数据冗余:主从复制实现了数据的热备份。
  • 故障恢复:当主节点出现问题时,可以根据哨兵选举出另外的主节点提供服务。
  • 负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务,在写少读多的场景下,通过多个从节点负担读负载,提升 Redis 服务器的并发量。
  • 高可用基石:除了上述作用之外,主从复制还是哨兵和集群能够实施的基础。

主从复制原理

  • 全量复制:例如第一次同步数据时
  • 增量复制:只会把主从库网络断连期间主库收到的命令,同步给从库

在 Redis 复制的基础上,使用和配置主从复制非常简单,能使得从 Redis 服务器 能精确地复制主服务器的数据。 主要依靠三个机制:

  • 当一个 master 实例和一个 slave 实例连接正常时,master 会发送一连串的命令流来保持对 slave 的更新,以便对 slave 的更新,以便将自身的数据集的改变复制给 slave: 包括客户端的写入、key 的过期或被逐出等待。
  • 当 master 和 slave 之间的连接断开之后,因为网络问题、或者时主从意识连接超时,slave 重新连接上 master 并会尝试 进行部分重同步:这意味着它会尝试只获取在断在连接期间内丢失的命令流
  • 当无法进行部分重同步时,slave 会请求进行全量同步。这会涉及一个更为复杂的过程,例如 master 需要创建所有数据的快照,将之发送 给 slave,之后在数据集更改时持续发送命令流到 slave

Redis 使用的默认是异步复制,其特点是低延迟和高性能,是绝大多数 Redis 用例的自然复制模式。但是, 从 Redis 服务器会异步地确认其从主 Redis 服务器周期接收到的数据量。

redis 复制过程

  1. 从节点执行 slaveof [masterIP] [masterPort] , 保存主节点信息
  2. 从节点中的定时任务发现主节点信息,建立与主节点的 socket 连接
  3. 从节点发送 Ping 信号,主节点返回 Pong, 互相通信
  4. 连接建立后,主节点将所有数据发送给从节点(数据同步)
  5. 主节点把当前的数据同步给从节点后,便完成了辅助的建立过程。接下来,主节点就会持续的把写命令发送给从节点, 保证主从数据一致性

为什么主从全量复制使用 RDB 而不使用 AOF ?

RDB 文件内容是经过压缩的二进制数据(不同数据类型数据做了针对性优化),文件很小。而 AOF 文件记录的是每一次写操作的命令,写操作越多文件会越大,其中还包括对同一个 key 的多次冗余操作。在主从全量数据同步时,传输 RDB 文件可以尽量降低对主库机器网络带宽的消耗。对于二进制数据,从库直接按照 RDB 协议还原数据即可,速度会非常快,而 AOF 需要依次重放每个写命令,这个过程会经历冗长的处理逻辑,恢复速度相比 RDB 会慢很多。所以使用 RDB 进行主从全量复制的成本最低。

读写分离及其中的问题

在主从复制基础上实现的读写分离,可以实现 Redis 的读负载均衡:由主节点提供写服务,由一个或多个从节点提供读服务;在读负载较大的应用场景下,可以大大提高 Redis 服务器的并发量。但是由于服务时异步的,也会存在相关问题:

  • 延迟与不一致问题

    由于主从复制的命令传播是异步的,延迟与数据一致性不可避免。若应用对数据不一致的接受程度较低,可能的优化措施包括:优化主从节点之间的网络环境(如同机房部署);监控主从节点延迟(通过 offset )判断,若从节点延迟较大,通知应用不再通过该从节点读取数据;使用集群同时扩展写负载和读负载等。

在命令传播阶段以外的其他情况下,从节点的数据不一致可能更加严重,例如连接在数据同步阶段,或从节点失去与主节点连接时等。从节点的 slave-serve-stale-data 参数便与此有关:它控制这种情况下从节点的表现;如果为 yes (默认值),则从节点仍然能够响应客户端的命令,如果为 no,则从节点只能响应 info\slaveof 等少数命令。若对数据一致性要求很高,则应设置为 no

  • 数据过期问题

    在单机版 Redis 中,存在两种删除策略:

    • 惰性删除:服务器不会主动删除数据,只有当客户端查询某个数据时,服务器判断该数据是否过期,若过期则删除。
    • 定期删除:服务器指定定时任务删除过期数据,但是考虑到内存和 CPU (删除会释放内存,但是频繁删除操作对 CPU 不太友好),该删除的频率和执行时间都受到了限制。

    对于定期删除而言,Redis 每秒 10 次:

    • 测试随机的 20 个 keys 进行相关过期检测
    • 删除所有已经过期的 keys
    • 如果有多于 25% 的 keys 过期,重复步骤 1.

    当不断进行重复时,知道过期的 keys 的百分比低于25%,在任何给定的时刻,最多会清除 1/4 的过期 keys。

参考:

https://pdai.tech/md/db/nosql-redis/db-redis-x-copy.html

http://www.redis.cn/topics/replication.html

-------------THANKS FOR READING-------------