db-tutorial/docs/redis/Redis复制.md

146 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

---
title: Redis 复制
date: 2018/06/19
categories:
- database
tags:
- database
- nosql
---
# Redis 复制
<!-- TOC depthFrom:2 depthTo:3 -->
- [Redis 复制要点](#redis-复制要点)
- [当主服务器不进行持久化时复制的安全性](#当主服务器不进行持久化时复制的安全性)
- [Redis 主从复制是如何工作的](#redis-主从复制是如何工作的)
- [部分重新同步](#部分重新同步)
- [无磁盘复制](#无磁盘复制)
- [配置](#配置)
- [只读从服务器](#只读从服务器)
- [设置从服务器到主服务器验证](#设置从服务器到主服务器验证)
- [限制有 N 个以上从服务器才允许写入](#限制有-n-个以上从服务器才允许写入)
- [资料](#资料)
<!-- /TOC -->
## Redis 复制要点
- Redis 使用异步复制。但从 Redis 2.8 开始,从服务器会周期性的应答从复制流中处理的数据量。
- 一个主服务器master可以有多个从服务器slave
- 从服务器也可以接受其他从服务器的连接。除了多个从服务器连接到一个主服务器之外,多个从服务器也可以连接到一个从服务器上,形成一个图状结构
- Redis 主从复制不阻塞主服务器端。也就是说当若干个从服务器在进行初始同步时,主服务器仍然可以处理请求。
- 主从复制也不阻塞从服务器端。当从服务器进行初始同步时,它使用旧版本的数据来应对查询请求,假设你在 redis.conf 配置文件是这么配置的。否则的话,你可以配置当复制流关闭时让从服务器给客户端返回一个错误。但是,当初始同步完成后,需要删除旧的数据集和加载新的数据集,在这个短暂的时间内,从服务器会阻塞连接进来的请求。
- 主从复制可以用来增强扩展性,使用多个从服务器来处理只读的请求(比如,繁重的排序操作可以放到从服务器去做),也可以简单的用来做数据冗余。
- 使用主从复制可以为主服务器免除把数据写入磁盘的消耗:在主服务器的 redis.conf 文件中配置“避免保存”(注释掉所有“保存“命令),然后连接一个配置为“进行保存”的从服务器即可。但是这个配置要确保主服务器不会自动重启(要获得更多信息请阅读下一段)
## 当主服务器不进行持久化时复制的安全性
在使用 Redis 复制功能时的设置中,强烈建议在 master 和在 slave 中启用持久化。当不可能启用时,例如由于非常慢的磁盘性能而导致的延迟问题,**应该配置实例来避免重置后自动重启**。
关闭了持久化并配置了自动重启的 master 是危险的,原因如下:
- 我们设置节点 A 为 master 并关闭它的持久化设置,节点 B 和 C 从 节点 A 复制数据。
- 节点 A 崩溃,但是他有一些自动重启的系统可以重启进程。但是由于持久化被关闭了,节点重启后其数据集合为空。
- 节点 B 和 节点 C 会从节点 A 复制数据,但是节点 A 的数据集是空的,因此复制的结果是它们会销毁自身之前的数据副本。
当在高可用系统中使用 Redis Sentinel关闭了主服务器的持久化并且允许自动重启这种情况是很危险的。比如主服务器可能在很短的时间就完成了重启以至于 Sentinel 都无法检测到这次失败,那么上面说的这种失败的情况就发生了。
如果数据比较重要,并且在使用主从复制时关闭了主服务器持久化功能的场景中,都应该禁止实例自动重启。
## Redis 主从复制是如何工作的
如果你设置了一个从服务器,在连接时它发送了一个 SYNC 命令,不管它是第一次连接还是再次连接都没有关系。
然后主服务器**开始后台存储**,并且开始缓存新连接进来的修改数据的命令。**当后台存储完成后,主服务器把数据文件发送到从服务器,从服务器将其保存在磁盘上,然后加载到内存中**。然后主服务器把刚才缓存的命令发送到从服务器。这是作为命令流来完成的,并且和 Redis 协议本身格式相同。
你可以通过 telnet 自己尝试一下。在 Redis 服务器工作时连接到 Redis 端口,发送 SYNC 命令,会看到一个批量的传输,并且主服务器接收的每一个命令都会通过 telnet 会话重新发送一遍。
当主从服务器之间的连接由于某些原因断开时,从服务器可以自动进行重连接。当有多个从服务器同时请求同步时,主服务器只进行一个后台存储。
当连接断开又重新连上之后,一般都会进行一个完整的重新同步,但是从 Redis2.8 开始,只重新同步一部分也可以。
## 部分重新同步
从 Redis 2.8 开始,如果遭遇连接断开,重新连接之后可以从中断处继续进行复制,而不必重新同步。
它的工作原理是这样,**主服务器端为复制流维护一个内存缓冲区in-memory backlog。主从服务器都维护一个复制偏移量replication offset和 master run id ,当连接断开时,从服务器会重新连接上主服务器,然后请求继续复制,假如主从服务器的两个 master run id 相同,并且指定的偏移量在内存缓冲区中还有效,复制就会从上次中断的点开始继续**。如果其中一个条件不满足,就会进行完全重新同步(在 2.8 版本之前就是直接进行完全重新同步)。因为主运行 id 不保存在磁盘中,如果从服务器重启了的话就只能进行完全同步了。
部分重新同步这个新特性内部使用 PSYNC 命令,旧的实现中使用 SYNC 命令。Redis2.8 版本可以检测出它所连接的服务器是否支持 PSYNC 命令,不支持的话使用 SYNC 命令。
## 无磁盘复制
通常来讲,一个完全重新同步需要在磁盘上创建一个 RDB 文件,然后加载这个文件以便为从服务器发送数据。
如果使用比较低速的磁盘这种操作会给主服务器带来较大的压力。Redis 从 2.8.18 版本开始尝试支持无磁盘的复制。使用这种设置时,子进程直接将 RDB 通过网络发送给从服务器,不使用磁盘作为中间存储。
这一特性目前只是实验性的。
## 配置
主从复制的配置十分简单:把下面这行加入到从服务器的配置文件中即可。
```
slaveof 192.168.1.1 6379
```
当然你需要把其中的 192.168.1.1 6379 替换为你自己的主服务器 IP或者主机名 hostname和端口。另外你可以调用 SLAVEOF 命令,主服务器就会开始与从服务器同步。
关于部分重新同步,还有一些针对复制内存缓冲区的优化参数。查看 Redis 介质中的 Redis.conf 示例获得更多信息。
使用 repl-diskless-sync 配置参数来启动无磁盘复制。使用 repl-diskless-sync-delay 参数来配置传输开始的延迟时间,以便等待更多的从服务器连接上来。查看 Redis 介质中的 Redis.conf 示例获得更多信息。
## 只读从服务器
从 Redis 2.6 开始,从服务器支持只读模式,并且是默认模式。这个行为是由 Redis.conf 文件中的 slave-read-only 参数控制的,可以在运行中通过 CONFIG SET 来启用或者禁用。
只读的从服务器会拒绝所有写命令,所以对从服务器不会有误写操作。但这不表示可以把从服务器实例暴露在危险的网络环境下,因为像 DEBUG 或者 CONFIG 这样的管理命令还是可以运行的。不过你可以通过使用 rename-command 命令来为这些命令改名来增加安全性。
你可能想知道为什么只读限制还可以被还原,使得从服务器还可以进行写操作。虽然当主从服务器进行重新同步或者从服务器重启后,这些写操作都会失效,还是有一些使用场景会想从服务器中写入临时数据的,但将来这个特性可能会被去掉。
## 设置从服务器到主服务器验证
如果主服务器设置了密码,配置从服务器在所有同步中使用这个密码十分简单。
对于运行中的实例,使用 redis-cli 并输入:
```xml
</pre>
<pre><code>config set masterauth <password></code></pre>
<pre>
```
要使配置永久生效,把如下命令加入到配置文件中:
```xml
</pre>
<pre><code>masterauth <password></code></pre>
<pre>
```
## 限制有 N 个以上从服务器才允许写入
从 Redis 2.8 版本开始,可以配置主服务器连接 N 个以上从服务器才允许对主服务器进行写操作。但是,因为 Redis 使用的是异步主从复制,没办法确保从服务器确实收到了要写入的数据,所以还是有一定的数据丢失的可能性。
这一特性的工作原理如下:
- 从服务器每秒钟 ping 一次主服务器,确认处理的复制流数量。
- 主服务器记住每个从服务器最近一次 ping 的时间。
- 用户可以配置最少要有 N 个服务器有小于 M 秒的确认延迟。
如果有 N 个以上从服务器,并且确认延迟小于 M 秒,主服务器接受写操作。
你可以把这看做是 CAP 原则(一致性,可用性,分区容错性)不严格的一致性实现,虽然不能百分百确保一致性,但至少保证了丢失的数据不会超过 M 秒内的数据量。
如果条件不满足,主服务器会拒绝写操作并返回一个错误。
- min-slaves-to-write最小从服务器数
- min-slaves-max-lag从服务器最大确认延迟
查看 Redis 介质中的 Redis.conf 示例获得更多信息。
## 资料
- http://ifeve.com/redis-replication/