🙊
关于作者
  • 个人简历
  • 联系作者
  • 运维日常记录
    • RAID 磁盘阵列
    • MBR 与 GPT 分区
    • Linux 命令行判断GPT和MBR分区
    • CentoS 7 系统 扩容根分区
  • Linux运维学习笔记
    • 计算机网络基础知识
    • Linux 系统启动过程
    • Linux 命令基本格式
    • Linux 文件删除原理
    • Linux 目录结构说明
    • Linux 查看命令帮助信息
    • Linux Yum 命令
    • Linux Apt 命令
  • Linux 运维管理
    • Linux 硬件管理
    • Linux 软件管理
    • Linux 磁盘管理
    • Linux 系统管理
    • Linux 网络管理
    • Linux 用户和组管理
    • Linux 文件与目录管理
    • Linux 文件压缩与解压缩管理
    • Linux SSL证书自动更新管理
  • 运维环境搭建
    • CentOS 7 安装与优化
    • CentOS 安装高版本Node.js
    • CentOS 升级安装Python2.7.X
    • CentOS 安装 Python3.8.X
    • CentOS 安装 PHP7.4.X
    • CentOS 安装 Mysql 8.0
    • CentOS 安装 Zabbix 5.0
    • Windows Server 部署 IIS
    • Cronsun 任务管理器部署
    • Teltport 堡垒机部署
    • Jump Server 堡垒机搭建及使用
    • CI & CD 持续集成部署
    • ELK6.5.0+Filebeat 日志系统部署
    • Lustre 分布式并行文件系统部署
  • 系统安全加固
    • Linux 操作系统加固
    • Windows 操作系统安全加固
    • Password 安全加固
    • OpenSSL 安全加固
    • NFS 服务安全加固
    • Rsync 服务安全加固
    • IIS 服务安全加固
    • PHP 语言环境安全加固
    • Apache 服务安全加固
    • Nginx 服务安全加固
    • Tomcat 服务安全加固
    • MySQL 服务安全加固
    • PostgreSQL 服务安全加固
    • Redis 服务安全加固
    • MongoDB 服务安全加固
    • 暴力破解攻击和防御
  • 云原生运维教程
    • Docker 理论
    • Docker 基本架构
    • Docker 基本概念
    • Docker 基本使用
      • 容器
      • 镜像
      • 仓库
    • Docker 存储
    • Docker 网络
    • Docker 安装
  • Linux 系统故障排查
    • Linux 系统重置密码方法
    • Linux 系统误操作修改目录权限为 777 修复方法
  • Windows 系统故障排查
    • Windows 和 Windows Server 中启用/禁用 SMBv1、SMBv2 和 SMBv3
    • Windows10建立映射网络驱动器报错,无法挂载共享文件系统,解决办法
  • 运维工具使用
    • 常用 Git 命令简介及使用
    • 常用 SVN 命令简介及使用
    • 常用 Vi / Vim 文本编辑工具简介及使用
    • 国内常用加速源使用及配置
    • 软碟通制作U启动和再生龙恢复Linux系统及备份
    • 常用JetBrains系列IDE快捷键
  • 中间件教程学习
    • Nginx 极简教程
    • Nginx 安装
    • Nginx 配置
    • Nginx 问题集
    • Mysql 教程
    • Mysql 运维
    • Mysql 原理
    • Redis 教程
    • Redis 持久化
    • Redis 复制
    • Redis 哨兵
    • Redis 集群
    • Redis 运维
    • PostgreSQL 教程
    • H2 教程
    • SqLite 教程
    • 数据库中间件 flyway
  • Nginx 入门教程
  • MySQL 入门教程
  • Nosql 数据库
  • 常用工具快捷键
    • Windows10常用快捷键大全
  • Group 1
由 GitBook 提供支持
在本页
  • 旧版复制功能
  • 同步
  • 命令传播
  • 旧版复制功能的缺陷
  • 新版复制功能
  • 部分重同步的实现
  • PSYNC 命令的实现
  • 复制的实现
  • 1. 设置主从服务器
  • 2. 主从服务器建立 TCP 连接。
  • 3. 发送 PING 检查通信状态。
  • 4. 身份验证。
  • 5. 发送端口信息。
  • 6. 同步。
  • 7. 命令传播。
  • 限制有 N 个以上从服务器才允许写入
  • Redis 复制要点
  • 参考资料

这有帮助吗?

  1. 中间件教程学习

Redis 复制

旧版复制功能

Redis 2.8 版本以前实现方式:SYNC 命令

Redis 的复制功能分为同步和命令传播两个操作:

  • 同步(sync) - 用于将从服务器的数据库状态更新至主服务器当前的数据库状态。

  • 命令传播(command propagate) - 当主服务器的数据库状态被修改,导致主从数据库状态不一致时,让主从服务器的数据库重新回到一致状态。

同步

命令传播

同步操作完成后,主从数据库的数据库状态将达到一致。每当主服务器执行客户端发送的写命令时,主从数据库状态不再一致。需要将写命令发送给从服务器执行,使得二者的数据库状态重新达到一致。

旧版复制功能的缺陷

从服务器对主服务器的复制存在两种情况:

  • 初次复制

  • 断线后重复制

对于初次复制,旧版复制功能可用很好完成任务;但是对于断线后重复制,由于每次任然需要生成 RDB 并传输,效率很低。

💡 注意:

SYNC 命令是一个非常耗费资源的操作。

  1. 主服务器执行 BGSAVE 命令生成 RDB 文件,这个操作会耗费主服务器大量的 CPU、内存和磁盘 I/O 资源。

  2. 主服务器传输 RDB 文件给从服务器,这个操作会耗费主从服务器大量的网络资源,并对主服务器响应时延产生影响。

  3. 从服务器载入 RDB 文件期间,会阻塞其他命令请求。

新版复制功能

Redis 2.8 版本以后的新实现方式:使用 PSYNC 命令替代 SYNC 命令。

PSYNC 命令具有完整重同步和部分重同步两种模式:

  • 完整重同步(full resychronization) - 用于初次复制。执行步骤与 SYNC 命令基本一致。

  • 部分重同步(partial resychronization) - 用于断线后重复制。如果条件允许,主服务器可以将主从服务器连接断开期间执行的写命令发送给从服务器,从服务器只需接收并执行这些写命令,即可将主从服务器的数据库状态保持一致。

部分重同步的实现

部分重同步功能实现由三个部分构成:

  • 复制偏移量(replication offset)

  • 复制积压缓冲区(replication backlog)

  • 服务器的运行 ID

它的工作原理是这样:主服务器端为复制流维护一个内存缓冲区(in-memory backlog)。主从服务器都维护一个复制偏移量(replication offset)和 master run id ,当连接断开时,从服务器会重新连接上主服务器,然后请求继续复制,假如主从服务器的两个 master run id 相同,并且指定的偏移量在内存缓冲区中还有效,复制就会从上次中断的点开始继续。如果其中一个条件不满足,就会进行完全重新同步(在 2.8 版本之前就是直接进行完全重新同步)。

复制偏移量

主服务器和从服务器会分别维护一个复制偏移量。

如果主从服务器的复制偏移量相同,则说明二者的数据库状态一致;反之,则说明二者的数据库状态不一致。

复制积压缓冲区

复制积压缓冲区会保存一部分最近传播的写命令,并且复制积压缓冲区会为队列中的每个字节记录相应的复制偏移量。

当从服务器断线重连主服务时,从服务器会通过 PSYNC 命令将自己的复制偏移量 offset 发送给主服务器,主服务器会根据这个复制偏移量来决定对从服务器执行何种同步操作。

  • 如果 offset 之后的数据仍然在复制积压缓冲区,则主服务器对从服务器执行部分重同步操作。

  • 反之,则主服务器对从服务器执行完整重同步操作。

复制积压缓冲区是由主服务器维护的一个固定长度的先进先出队列,默认大小为 1MB。

🔔 注意:合理调整复制积压缓冲区的大小

Redis 复制积压缓冲区默认大小为 1MB。

复制积压缓冲区的最小大小可以根据公式 second * write_size_per_second 估算。

服务器的运行 ID

  • 每个 Redis 服务器,都有运行 ID,用于唯一识别身份。

  • 运行 ID 在服务器启动时自动生成,由 40 个随机的十六进制字符组成。例如:132e358005e29741f8d7b0a42d666aace286edda

从服务器对主服务器进行初次复制时,主服务器会将自己的运行 ID 传送给从服务器,从服务器会将这个运行 ID 保存下来。

当从服务器断线重连一个主服务器时,从服务器会发送之前保存的运行 ID:

  • 如果保存的运行 ID 和当前主服务器的运行 ID 一致,则说明从服务器断线之前连接的就是这个主服务器,主服务器可以继续尝试执行部分重同步操作;

  • 反之,若运行 ID 不一致,则说明从服务器断线之前连接的不是这个主服务器,主服务器将对从服务器执行完整重同步操作。

PSYNC 命令的实现

复制的实现

1. 设置主从服务器

配置一个从服务器非常简单, 只要在配置文件中增加以下的这一行就可以了:

slaveof 192.168.1.1 6379

当然, 你需要将代码中的 192.168.1.1 和 6379 替换成你的主服务器的 IP 和端口号。

127.0.0.1:6379> SLAVEOF 192.168.1.1 10086
OK

2. 主从服务器建立 TCP 连接。

3. 发送 PING 检查通信状态。

4. 身份验证。

如果主服务器没有设置 requirepass ,从服务器没有设置 masterauth,则不进行身份验证;反之,则需要进行身份验证。如果身份验证失败,则放弃执行复制工作。

如果主服务器通过 requirepass 选项设置了密码, 那么为了让从服务器的同步操作可以顺利进行, 我们也必须为从服务器进行相应的身份验证设置。

对于一个正在运行的服务器, 可以使用客户端输入以下命令:

config set masterauth <password>

要永久地设置这个密码, 那么可以将它加入到配置文件中:

masterauth <password>

另外还有几个选项, 它们和主服务器执行部分重同步时所使用的复制流缓冲区有关, 详细的信息可以参考 Redis 源码中附带的 redis.conf 示例文件。

5. 发送端口信息。

从服务器执行 REPLCONF listening-port <port-number> ,向主服务器发送从服务器的监听端口号。

6. 同步。

前文已介绍,此处不赘述。

7. 命令传播。

在命令传播阶段,从服务器默认会以每秒一次的频率,向主服务发送命令:

REPLCONF ACK <replication_coffset>

命令的作用:

  • 检测主从服务器的网络连接状态。

  • 辅助实现 min-slave 选项。

  • 检测命令丢失。

限制有 N 个以上从服务器才允许写入

从 Redis 2.8 开始, 为了保证数据的安全性, 可以通过配置, 让主服务器只在有至少 N 个当前已连接从服务器的情况下, 才执行写命令。

不过, 因为 Redis 使用异步复制, 所以主服务器发送的写数据并不一定会被从服务器接收到, 因此, 数据丢失的可能性仍然是存在的。

以下是这个特性的运作原理:

  • 从服务器以每秒一次的频率 PING 主服务器一次, 并报告复制流的处理情况。

  • 主服务器会记录各个从服务器最后一次向它发送 PING 的时间。

  • 用户可以通过配置, 指定网络延迟的最大值 min-slaves-max-lag , 以及执行写操作所需的至少从服务器数量 min-slaves-to-write 。

如果至少有 min-slaves-to-write 个从服务器, 并且这些服务器的延迟值都少于 min-slaves-max-lag秒, 那么主服务器就会执行客户端请求的写操作。

你可以将这个特性看作 CAP 理论中的 C 的条件放宽版本: 尽管不能保证写操作的持久性, 但起码丢失数据的窗口会被严格限制在指定的秒数中。

另一方面, 如果条件达不到 min-slaves-to-write 和 min-slaves-max-lag 所指定的条件, 那么写操作就不会被执行, 主服务器会向请求执行写操作的客户端返回一个错误。

以下是这个特性的两个选项和它们所需的参数:

  • min-slaves-to-write <number of slaves>

  • min-slaves-max-lag <number of seconds>

详细的信息可以参考 Redis 源码中附带的 redis.conf 示例文件。

Redis 复制要点

  • Redis 使用异步复制。 从 Redis 2.8 开始, 从服务器会以每秒一次的频率向主服务器报告复制流(replication stream)的处理进度。

  • 一个主服务器可以有多个从服务器。

  • 不仅主服务器可以有从服务器, 从服务器也可以有自己的从服务器, 多个从服务器之间可以构成一个图状结构。

  • 复制功能不会阻塞主服务器: 即使有一个或多个从服务器正在进行初次同步, 主服务器也可以继续处理命令请求。

  • 复制功能也不会阻塞从服务器: 只要在 redis.conf 文件中进行了相应的设置, 即使从服务器正在进行初次同步, 服务器也可以使用旧版本的数据集来处理命令查询。

    不过, 在从服务器删除旧版本数据集并载入新版本数据集的那段时间内, 连接请求会被阻塞。

    你还可以配置从服务器, 让它在与主服务器之间的连接断开时, 向客户端发送一个错误。

  • 可以通过复制功能来让主服务器免于执行持久化操作: 只要关闭主服务器的持久化功能, 然后由从服务器去执行持久化操作即可。

  • 在使用 Redis 复制功能时的设置中,强烈建议在 master 和在 slave 中启用持久化。当不启用时,例如由于非常慢的磁盘性能而导致的延迟问题,应该配置实例来避免重置后自动重启。

  • 从 Redis 2.6 开始, 从服务器支持只读模式, 并且该模式为从服务器的默认模式。

    • 只读从服务器会拒绝执行任何写命令, 所以不会出现因为操作失误而将数据不小心写入到了从服务器的情况。

参考资料

  • 《Redis 实战》

  • 《Redis 设计与实现》

上一页Redis 持久化下一页Redis 哨兵

最后更新于5年前

这有帮助吗?

另外一种方法是调用 命令, 输入主服务器的 IP 和端口, 然后同步就会开始:

复制功能可以单纯地用于数据冗余(data redundancy), 也可以通过让多个从服务器处理只读命令请求来提升扩展性(scalability): 比如说, 繁重的 [SORT key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern …]] [ASC | DESC] [ALPHA] [STORE destination]]() 命令可以交给附属节点去运行。

只读模式由 redis.conf 文件中的 slave-read-only 选项控制, 也可以通过 命令来开启或关闭这个模式。

SLAVEOF host port
http://redisdoc.com/database/sort.html#sort
CONFIG SET parameter value
http://redisdoc.com/topic/replication.html