<commit_before>---
layout: post
title: "【译】Redis Replication"
subtitle: ""
date: 2018-01-07
author: "ChenJY"
header-img: "img/code1.jpg"
catalog: true
tags: 
    - Redis
    - 翻译
---

> 翻译自 https://redis.io/topics/replication

## 复制

就 Redis 复制而言，有一个非常简单的方式去使用和配置主从复制，能使得从 Redis 服务器能精确得复制主 Redis 服务器的内容。每次当从服务器在和主服务器之间的连接断开时，从服务器会自动重连到主服务器上，并且无论这期间主服务器发生了什么，从服务器都会尝试更新自身到主服务器最新的状态。

这个系统的运行依靠三个主要的机制：

* 当一个主服务器实例和一个从服务器实例连接正常时，主服务器为了将自身数据集的改变复制给从服务器，会通过发送一连串的命令流来更新从服务器：包括客户端的写入、key 的过期或被逐出等等。
* 当主从服务器之间的连接断开之后，因为网络问题或者是主或从意识到了连接超时的现象，从服务器重新连接上主服务器并会尝试进行部分重同步：这表示它会尝试只获取在断开连接期间内丢失的命令流。
* 当无法进行部分重同步时，从服务器会请求进行全量重同步。这会导致更复杂的操作，例如主服务器需要以自身所有的数据创建一个镜像，将之发送给从服务器，之后再持续发送改变其数据集的命令流到从服务器。

Redis使用默认的异步复制，其特点是高延迟和高性能，是绝大多数 Redis 用例的主要复制模式。不管从 Redis 服务器是如何异步地确认其从主 Redis 服务器周期接收到的数据量的。

客户端可以使用 WAIT 命令来请求同步复制某些特定的数据。但是，WAIT 命令只能确保在其他 Redis 实例中有指定数量的已确认的副本：在故障转移期间，由于不同原因的故障转移或是由于 Redis 持久性的实际配置，已确认的写操作可能仍然会丢失。您可以查看 Sentinel 或 Redis 集群文档，了解关于高可用性和故障转移的更多信息。本文档的其余部分主要描述了 Redis 基本复制功能的基本特性。

接下来的是一些关于 Redis 复制的非常重要的事实：
* Redis 使用异步复制，异步的主从之间确认处理的数据量
* 一个主服务器可以拥有多个从服务器
* 从服务器可以接受其他从服务器的连接。除了多个从服务器可以连接到同一个主服务器，从服务器之间也可以像层次结构（cascading-like structure）一样连接。自 Redis 4.0 起，所有的子-从服务器将会从主服务器收到完全一样的复制流。
* Redis 复制在主服务器侧是非阻塞的。这意味着主服务器在一个或多个从服务器进行初次同步或者是部分重同步时，可以继续处理请求。
* 复制在从服务器侧也是大部分非阻塞的。当从服务器进行初次同步时，它可以使用旧数据集处理请求，假设你在 redis.conf 中配置了让 Redis 这样做的话。否则，你可以配置如果复制流断开， Redis 从服务器会返回一个 error 给客户端。但是，在初次同步之后，旧数据集必须被删掉同时加载新数据集。从服务器在这个短暂的时间窗口内（如果数据集很大，会持续较长时间），会阻塞即将到来的连接请求。自 Redis 4.0 开始，配置 Redis 使删除旧数据集的操作在另一个不同的线程中进行是可行的，但是，加载新数据集的操作依然需要在主线程中进行并且会阻塞从服务器。
* 复制可以被运用在可伸缩功能，以便只读查询可以有多个从服务器进行（例如 O(N) 复杂度的慢操作可以被下放到从服务器），或者简单地用于数据安全。
* 可以使用复制来避免主服务器将全部数据集写入磁盘造成的开销：一种典型的技术是配置你的主 Redis.conf 可以避免对磁盘进行持久化，然后连接一个从服务器，其配置为不时得保存或是启用 AOF。但是，这个设置必须小心处理，因为重新启动的主程序将从一个空数据集开始：如果一个从服务器试图与它同步，那么这个从服务器也会被清空。

## 当主服务器关闭持久化时，复制的安全性

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

为了更好地理解为什么关闭了持久化并配置了自动重启的主服务器是危险的，检查以下失败模式，这些失败模式中数据会从主服务器和所有从服务器中被删除：

* <commit_msg>update blog translation redis replication<commit_after>---
layout: post
title: "【译】Redis Replication"
subtitle: ""
date: 2018-01-07
author: "ChenJY"
header-img: "img/code1.jpg"
catalog: true
tags: 
    - Redis
    - 翻译
---

> 翻译自 [Redis Replication](https://redis.io/topics/replication)

## 复制

就 Redis 复制而言，有一个非常简单的方式去使用和配置主从复制，能使得从 Redis 服务器能精确得复制主 Redis 服务器的内容。每次当从服务器在和主服务器之间的连接断开时，从服务器会自动重连到主服务器上，并且无论这期间主服务器发生了什么，从服务器都会尝试更新自身到主服务器最新的状态。

这个系统的运行依靠三个主要的机制：

* 当一个主服务器实例和一个从服务器实例连接正常时，主服务器为了将自身数据集的改变复制给从服务器，会通过发送一连串的命令流来更新从服务器：包括客户端的写入、key 的过期或被逐出等等。
* 当主从服务器之间的连接断开之后，因为网络问题或者是主或从意识到了连接超时的现象，从服务器重新连接上主服务器并会尝试进行部分重同步：这表示它会尝试只获取在断开连接期间内丢失的命令流。
* 当无法进行部分重同步时，从服务器会请求进行全量重同步。这会导致更复杂的操作，例如主服务器需要以自身所有的数据创建一个镜像，将之发送给从服务器，之后再持续发送改变其数据集的命令流到从服务器。

Redis使用默认的异步复制，其特点是高延迟和高性能，是绝大多数 Redis 用例的主要复制模式。不管从 Redis 服务器是如何异步地确认其从主 Redis 服务器周期接收到的数据量的。

客户端可以使用 WAIT 命令来请求同步复制某些特定的数据。但是，WAIT 命令只能确保在其他 Redis 实例中有指定数量的已确认的副本：在故障转移期间，由于不同原因的故障转移或是由于 Redis 持久性的实际配置，已确认的写操作可能仍然会丢失。您可以查看 Sentinel 或 Redis 集群文档，了解关于高可用性和故障转移的更多信息。本文档的其余部分主要描述了 Redis 基本复制功能的基本特性。

接下来的是一些关于 Redis 复制的非常重要的事实：
* Redis 使用异步复制，异步的主从之间确认处理的数据量
* 一个主服务器可以拥有多个从服务器
* 从服务器可以接受其他从服务器的连接。除了多个从服务器可以连接到同一个主服务器，从服务器之间也可以像层次结构（cascading-like structure）一样连接。自 Redis 4.0 起，所有的子-从服务器将会从主服务器收到完全一样的复制流。
* Redis 复制在主服务器侧是非阻塞的。这意味着主服务器在一个或多个从服务器进行初次同步或者是部分重同步时，可以继续处理请求。
* 复制在从服务器侧也是大部分非阻塞的。当从服务器进行初次同步时，它可以使用旧数据集处理请求，假设你在 redis.conf 中配置了让 Redis 这样做的话。否则，你可以配置如果复制流断开， Redis 从服务器会返回一个 error 给客户端。但是，在初次同步之后，旧数据集必须被删掉同时加载新数据集。从服务器在这个短暂的时间窗口内（如果数据集很大，会持续较长时间），会阻塞即将到来的连接请求。自 Redis 4.0 开始，配置 Redis 使删除旧数据集的操作在另一个不同的线程中进行是可行的，但是，加载新数据集的操作依然需要在主线程中进行并且会阻塞从服务器。
* 复制可以被运用在可伸缩功能，以便只读查询可以有多个从服务器进行（例如 O(N) 复杂度的慢操作可以被下放到从服务器），或者简单地用于数据安全。
* 可以使用复制来避免主服务器将全部数据集写入磁盘造成的开销：一种典型的技术是配置你的主 Redis.conf 可以避免对磁盘进行持久化，然后连接一个从服务器，其配置为不定期保存或是启用 AOF。但是，这个设置必须小心处理，因为重新启动的主程序将从一个空数据集开始：如果一个从服务器试图与它同步，那么这个从服务器也会被清空。

## 当主服务器关闭持久化时，复制的安全性

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

为了更好地理解为什么关闭了持久化并配置了自动重启的主服务器是危险的，检查以下失败模式，这些失败模式中数据会从主服务器和所有从服务器中被删除：

1. 我们设置节点 A 为主节点并关闭它的持久化设置，节点 B 和 C 从 节点 A 复制数据。
2. 节点 A 崩溃，但是他有一些自动重启的系统可以重启进程。但是由于持久化被关闭了，节点重启后其数据集合为空。
3. 节点 B 和 节点 C 会从节点 A 复制数据，但是节点 A 的数据集是空的，因此复制的结果是它们会销毁自身之前的数据副本。

当 Redis 哨兵（Sentinel）被用于高可用并且主节点关闭持久化，这时如果允许自动重启进程是很危险的。例如，主服务器可以重启的足够快以致于哨兵没有探测到故障，所以上述的故障模式将会发生。

任何时候数据安全性都是很重要的，所以如果主服务器使用复制功能的同时未配置持久化，那么自动重启进程这项应该被禁用。

## Redis 复制功能是如何工作的
每一个 Redis 主服务器都有一个复制ID（Replication ID）：这是一个较大的伪随机字符串，标记了一个给定的数据集。每个主服务器也持有一个偏移量，它将自己产生的复制流发送给从服务器时，发送多少个字节的数据，自身的偏移量就会增加多少，目的是当有新的操作修改自身数据集时，它可以以此更新从服务器的状态。复制偏移量即使在没有一个从服务器连接到主服务器时，也会自增，所以基本上每个给定的

> Replication ID, offset

都会标识一个主服务器数据集的准确版本。

当从服务器连接到主服务器时，它们使用 PSYNC 命令来发送它们记录的旧的主节点复制 ID 和它们至今为止处理的偏移量。通过这种方式，主服务器能够仅发送从服务器所需的增量部分。但是如果主服务器的缓冲区中没有足够的积压记录，或者如果从服务器发送过来的历史记录（复制 ID）不是已知的，那么会进行一个全量重同步：在这种情况下，从服务器会得到一个完整的数据集副本，从头开始。

{'fraction_non_alphanumeric': 0.07579870536646481, 'fraction_numerical': 0.006055543954896638, 'mean_word_length': 11.807486631016042, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 6, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6031406', 'n_tokens_mistral': 4126, 'n_tokens_neox': 4805, 'n_words': 237}