在 Redis 集群中, 让若干个 Redis 服务器去复制另一个 Redis 服务器, 我们定义被复制的服务器为主服务器(master), 而对主服务器进行复制的服务器则被称为从服务器(slave), 这种模式叫做主从复制模式.
数据流向是单向的, 只能是从 master 到 slave
一个 slave 只能有一个 master
主从复制的作用
为数据提供多个副本, 实现高可用
实现读写分离(主节点负责写数据, 从节点负责读数据, 主节点定期把数据同步到从节点保证数据的一致性)
主从复制的方式
命令 slaveof.
优点: 无需重启. 缺点: 不便于管理
- // 命令行使用
- slaveof ip port // 使用命令后自身数据会被清空, 但取消 slave 只是停止复制, 并不清空
修改配置.
优点: 统一配置. 缺点: 需要重启
- // 配置文件中配置
- slaveof ip port
- slave-read-only yes // 只允许从节点进行读操作
全量复制
用于初次复制或其它无法进行部分复制的情况, 将主节点中的所有数据都发送给从节点, 是一个非常重型的操作, 当数据量较大时, 会对主从节点和网络造成很大的开销
全量复制过程:
Redis 内部会发出一个同步命令, 刚开始是 Psync 命令, Psync ? -1 表示要求 master 主机同步数据
主机会向从机发送 run_id 和 offset, 因为 slave 并没有对应的 offset, 所以是全量复制
从机 slave 会保存主机 master 的基本信息
主节点收到全量复制的命令后, 执行 bgsave(异步执行), 在后台生成 RDB 文件 (快照), 并使用一个缓冲区(称为复制缓冲区) 记录从现在开始执行的所有写命令
主机发送 RDB 文件给从机
发送缓冲区数据
刷新旧的数据. 从节点在载入主节点的数据之前要先将老数据清除
加载 RDB 文件将数据库状态更新至主节点执行 bgsave 时的数据库状态和缓冲区数据的加载.
全量复制开销
主节点需要 bgsave
RDB 文件网络传输占用网络 io
从节点要清空数据
从节点加载 RDB
全量复制会触发从节点 AOF 重写
部分复制
部分复制是 Redis 2.8 以后出现的, 用于处理在主从复制中因网络闪断等原因造成的数据丢失场景, 当从节点再次连上主节点后, 如果条件允许, 主节点会补发丢失数据给从节点. 因为补发的数据远远小于全量数据, 可以有效避免全量复制的过高开销, 需要注意的是, 如果网络中断时间过长, 造成主节点没有能够完整地保存中断期间执行的写命令, 则无法进行部分复制, 仍使用全量复制
部分复制过程:
如果网络抖动(连接断开 connection lost)
主机 master 还是会写 repl_back_buffer(复制缓冲区)
从机 slave 会继续尝试连接主机
从机 slave 会把自己当前 run_id 和偏移量传输给主机 master, 并且执行 pysnc 命令同步
如果 master 发现你的偏移量是在缓冲区的范围内, 就会返回 continue 命令
同步了 offset 的部分数据, 所以部分复制的基础就是偏移量 offset.
服务器运行 ID(run_id): 每个 Redis 节点(无论主从), 在启动时都会自动生成一个随机 ID(每次启动都不一样), 由 40 个随机的十六进制字符组成; run_id 用来唯一识别一个 Redis 节点. 通过 info server 命令, 可以查看节点的 run_id.
开发运维常见的问题
读写分离
复制数据存在延迟(如果从节点发生阻塞)
从节点可能发生故障
主从配置不一致
例如 maxmemory 不一致, 可能会造成丢失数据
例如数据结构优化参数不一致: 造成主从内存不一致
规避全量复制
第一次全量复制不可避免, 所以分片的 maxmemory 减小, 同时选择在低峰 (夜间) 时, 做全量复制.
复制积压缓冲区不足
增大复制缓冲区配置 rel_backlog_size
例如如果网络中断的平均时间是 60s, 而主节点平均每秒产生的写命令 (特定协议格式) 所占的字节数为 100KB, 则复制积压缓冲区的平均需求为 6MB, 保险起见, 可以设置为 12MB, 来保证绝大多数断线情况都可以使用部分复制.
复制风暴
master 节点重启, master 节点生成一份 rdb 文件, 但是要给所有从节点发送 rdb 文件. 对 CPU, 内存, 带宽都造成很大的压力
来源: https://www.cnblogs.com/mseddl/p/11470900.html