Redis 高级应用 -- 主从复制

本贴最后更新于 1832 天前,其中的信息可能已经斗转星移

简介

高并发

互联网架构追求高并发,高性能和高可用。其中高并发指允许大量用户同时访问,高可用指服务器宕机时间少。业界高可用目标为 5 个 9,即可用性达到 99.999%,也就是说服务器年宕机时长低于 315 秒,计算公式为:(31536000-宕机时间)/ 31536000 * 100% (31536000 = 365 * 24* 60 * 60=1 年)

主从复制作用

1、读写分离:master 写,slave 读,提高服务器的读写负载能力
2、负载均衡:基于主从结构,配合读写分离,由 slave 分担 master 负载,并根据需求的变化,改变 slave 的数量,通过多个从节点分担数据读取负载,由 slave 提供服务,实现快速的故障恢复
3、故障恢复:当 master 出现问题时,由 slave 提供服务,实现快速的故障恢复
4、数据冗余:实现数据热备份,是持久化之外的一种数据冗余方式
5、高可用基石:基于主从复制,构建哨兵模式与集群,实现 Redis 的高可用方案

主从复制工作流程

主从复制可分为三个阶段:

  • 建立连接阶段
  • 数据同步阶段
  • 命令传播阶段

建立连接阶段工作流程

master slave
/ 1、发送指令:slaveof ip port
2、接收指令,响应 slave /
/ 3、保存 master 的 ip 和端口
/ 4、根据保存的信息创建连接 master 的 socket
/ 5、周期性发送命令:ping
6、响应 pong /
/ 7、发送指令:auth password
8、验证授权 /
/ 9、发送指令:replconflistening-port
10、保存 slave 的端口号 /

主从连接指令(slave 使用)

方式一:客户端发送命令

slaveof <masterip> <masterport>

方式二:启动 slave 服务器时加参数

redis-server -slaveof  <masterip> <masterport>

方式三:服务器配置(保存在 conf 文件中)

slaveof <masterip> <masterport>

主从断开连接(slave 使用)

slave 客户端发送命令:

slaveof no one

数据同步阶段工作流程

master slave
/ 1、发送指令:psync2
2、执行 bgsave /
3、第一个 slave 连接时,创建复制缓冲区(复制缓存区中保存生成 RDB 文件时 master 服务器执行的命令) /
4、生成 RDB 文件,通过 socket 发送给 slave /
/ 5、接收 RDB 文件,清空数据,执行 RDB 文件恢复过程
/ 6、发送命令告知 RDB 恢复已经完成
7、发送复制缓冲区数据 /
/ 8、接收信息,执行 bgrewriteaof,恢复数据

数据同步阶段,1-5 称为全量复制,使用 RDB 方式同步;6-8 称为部分复制,使用 AOF 方式同步。这是因为全量复制时,还会有 master 服务器还会执行指令,因此需要保存这些指令,待全量复制后,同步这一部分数据。

部分复制阶段

短时间断网,可以使用部分复制来实现同步,而不必全量复制。使用部分数据需要三个要素:

  • 服务器运行 id(run id);
  • 主服务器的复制积压缓冲区
  • 主从服务器的复制偏移量
服务器运行 id
  • 服务器运行 id 是每台服务器运行时的身份识别码,一台服务器运行多次可以生成多个运行 id
  • 运行 id 由 40 位字符组成,是随机十六进制字符
  • 用于服务器之间传输,识别身份
复制缓冲区
  • 复制缓冲区又叫复制积压缓冲区,是一个先进先出的队列,用于存储服务器执行过的命令,每次传播命令,master 将命令记下来,存储在复制缓冲区。例如下面命令:
set name gavin

保存为 AOF 格式为:

$3 \r\n  #3表示指令的大小
set \r\n
$4 \r\n
name \r\n
$5 \r\n
gavin \r\n

然后将上面的数据保存在复制缓冲区中,复制缓冲区由偏移量和字节值组成,字节值表示上面指令,偏移量表示每个字节值代表的递增编号:

偏移量 9041 9042 9043 9044 9045 9046 9047 9048 9049 9050 9051 9052 9053 9054
字节值 ... $ 3 \r \n s e t \r \n $ 4 \r ...
偏移量
  • 偏移量是一个数字,描述缓冲区中指令字节位置
  • master 端每发送一次指令记录一次,slave 端接收一次指令记录一次
  • slave 断线后对比 master 和 slave 的差异,然后恢复数据
master slave
/ 1、发送指令: psync2 runid offset
2、执行 bgsave 生成 RDB 文件,记录当前复制偏移量 offset /
3、发送 +FULLRESYNC runid offset 发送 RDB 文件给 slave /
/ 4、收到 +FULLRESYNC 保存 master 的 runid 和 offset,清空全部数据,接收 RDB 文件,恢复 RDB 数据
/ 5、发送命令:psync2 runid offset
6、接收命令,判断 runid 是否匹配,判断 offset 是否在复制缓冲区中 /
7、如果 runid 或 offset 有一个不满足,执行全量复制 /
7、如果 runid 或 offset 校验通过,offset 与 offset 相同,忽略,不用执行同步 /
7、如果 runid 或 offset 校验通过,offset 与 offset 不同,发送 + CONTINUE offset ,发送复制缓冲区中两个 offset 之间的数据 /
/ 8、收到 +CONTINUE 保存 master 的 offset 接收 信息后,执行 bgrewriteaof,恢复数据

命令传播阶段工作流程

心跳机制

  • master 心跳:
    • 指令:PING
    • 周期:由 repl-ping-slave-period 决定,默认 10 秒
    • 作用:判断 slave 是否在线
    • 查询:INFO replication (获取 slave 最后一次连接时间间隔,lag 维持在 0 或者 1 视为正常)
  • slave 心跳
    • 指令:REPLCONF ACK {offset}
    • 周期:1 秒
    • 作用:汇报 slave 自己的复制偏移量,获取追星数据变更指令,判断 master 是否在线
min-slaves-to-write 2  
min-slaves-max-lag 8

slave 数量少于 2 个,或者所有 slave 的延迟都大于等于 8 时,此时 master 只能读,不能写,同时关闭数据同步功能。

命令传播

master slave
1、发送命令:ping 1、发送命令:replconf ack offset
2、接收命令,判断 offset 是否在复制缓冲区中 /
3、offset 不在缓冲区,执行全量复制 /
3、如果 offset 在缓冲区,master 的 offset 与 slave 的 offset 相同,忽略,不用执行同步 /
3、如果 offset 在缓冲区,master 的 offset 与 slave 的 offset 不同,发送 + CONTINUE offset ,发送复制缓冲区中两个 offset 之间的数据 /
/ 4、收到 +CONTINUE 保存 master 的 offset 接收 信息后,执行 bgrewriteaof,恢复数据

数据同步说明

1、复制缓冲区大小设定不合理,会导致数据溢出。如进行全量复制周期太长,进行部分复制时发现数据已经存在丢失情况,必须进行第二次全量复制,导致 slave 陷入死循环,因此可以设置复制缓冲区大小:

repl-backlog-size 1mb

2、master 单机内存占用主机内存比例不应过大,建议使用 50%~70% 的内存,留下 30%~50% 的内存用于执行 bgsave 命令和创建复制缓冲区。
3、为避免 slave 进行全量复制、部分复制时服务器响应阻塞或数据不同步,建议关闭此期间的对外服务

slave-serve-stale-data yes|no
  • Redis

    Redis 是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。从 2010 年 3 月 15 日起,Redis 的开发工作由 VMware 主持。从 2013 年 5 月开始,Redis 的开发由 Pivotal 赞助。

    286 引用 • 248 回帖 • 44 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...