Redis 主从 Replication 的配置

本专栏与Redis相关的文章redis

Redis Sentinel机制与用法(一)
Redis Sentinel机制与用法(二)
Jedis的JedisSentinelPool源代码分析
Jedis的Sharded源代码分析
Redis 主从 Replication 的配置
详解Redis SORT命令
JedisCommand接口说明segmentfault

本文参考翻译自 《Redis Replication documentation》

概述

Redis的replication机制容许slave从master那里经过网络传输拷贝到完整的数据备份。具备如下特色:缓存

  • 异步复制。从2.8版本开始,slave能不时地从master那里获取到数据。
  • 容许单个master配置多个slave
  • slave容许其它slave链接到本身。一个slave除了能够链接master外,它还能够链接其它的slave。造成一个图状的架构。
  • master在进行replication时是非阻塞的,这意味着在replication期间,master依然可以处理客户端的请求。
  • slave在replication期间也是非阻塞的,也能够接受来自客户端的请求,可是它用的是以前的旧数据。能够经过配置来决定slave是否在进行replication时用旧数据响应客户端的请求,若是配置为否,那么slave将会返回一个错误消息给客户端。不过当新的数据接收彻底后,必须将新数据与旧数据替换,即删除旧数据,在替换数据的这个时间窗口内,slave将会拒绝客户端的请求和链接。
  • 通常使用replication来能够实现扩展性,例如说,能够将多个slave配置为“只读”,或者是纯粹的数据冗余备份。
  • 可以经过replication来避免master每次持久化时都将整个数据集持久化到硬盘中。只需把master配置为不进行save操做(把配置文件中save相关的配置项注释掉便可),而后链接上一个slave,这个slave则被配置为不时地进行save操做的。不过须要注意的是,在这个用例中,必须确保master不会自动启动。更多详情请继续往下读。

Master持久化功能关闭时Replication的安全性

当有须要使用到replication机制时,通常都会强烈建议把master的持久化开关打开。即便为了不持久化带来的延迟影响,不把持久化开关打开,那么也应该把master配置为不会自动启动的。安全

为了更好地理解当一个不进行持久化的master若是容许自动启动所带来的危险性。能够看看下面这种失败情形:微信

假设咱们有一个redis节点A,设置为master,而且关闭持久化功能,另外两个节点B和C是它的slave,并从A复制数据。
若是A节点崩溃了致使全部的数据都丢失了,它会有重启系统来重启进程。可是因为持久化功能被关闭了,因此即便它重启了,它的数据集是空的。
而B和C依然会经过replication机制从A复制数据,因此B和C会从A那里复制到一份空的数据集,并用这份空的数据集将本身自己的非空的数据集替换掉。因而就至关于丢失了全部的数据。

即便使用一些HA工具,好比说sentinel来监控master-slaves集群,也会发生上述的情形,由于master可能崩溃后迅速恢复。速度太快而致使sentinel没法察觉到一个failure的发生。网络

当数据的安全很重要、持久化开关被关闭而且有replication发生的时候,那么应该禁止实例的自启动。架构

replication工做原理

若是你为master配置了一个slave,无论这个slave是不是第一次链接上Master,它都会发送一个SYNC命令给master请求复制数据。并发

master收到SYNC命令后,会在后台进行数据持久化,持久化期间,master会继续接收客户端的请求,它会把这些可能修改数据集的请求缓存在内存中。当持久化进行完毕之后,master会把这份数据集发送给slave,slave会把接收到的数据进行持久化,而后再加载到内存中。而后,master再将以前缓存在内存中的命令发送给slave。less

当master与slave之间的链接因为某些缘由而断开时,slave可以自动重连Master,若是master收到了多个slave并发链接请求,它只会进行一次持久化,而不是一个链接一次,而后再把这一份持久化的数据发送给多个并发链接的slave。异步

当master和slave断开重连后,通常都会对整份数据进行复制。但从redis2.8版本开始,支持部分复制。

数据部分复制

从2.8版本开始,slave与master可以在网络链接断开重连后只进行部分数据复制。

master会在其内存中建立一个复制流的等待队列,master和它全部的slave都维护了复制的数据下标和master的进程id,所以,当网络链接断开后,slave会请求master继续进行未完成的复制,从所记录的数据下标开始。若是进程id变化了,或者数据下标不可用,那么将会进行一次所有数据的复制。

支持部分数据复制的命令是PSYNC

不需硬盘参与的Replication

通常状况下,一次复制须要将内存的数据写到硬盘中,再将数据从硬盘读进内存,再发送给slave。

对于速度比较慢的硬盘,这个操做会给master带来性能上的损失。Redis2.8版本开始,实验性地加上了无硬盘复制的功能。这个功能能将数据从内存中直接发送到slave,而不用通过硬盘的存储。

不过这个功能目前处于实验阶段,还未正式发布。

相关配置

与replication相关的配置比较简单,只须要把下面一行加到slave的配置文件中:

slaveof 192.168.1.1 6379

你只须要把ip地址和端口号改一下。固然,你也能够经过客户端发送SLAVEOF命令给slave。

部分数据复制有一些可调的配置参数,请参考redis.conf文件。

无硬盘复制功能能够经过repl-diskless-sync来配置,另一个配置项repl-diskless-sync-delay用来配置当收到第一个请求时,等待多个slave一块儿来请求之间的间隔时间。

只读的slave

从redis2.6版本开始,slave支持只读模式,并且是默认的。能够经过配置项slave-read-only来进行配置,而且支持客户端使用CONFIG SET命令来动态修改配置。

只读的slave会拒绝全部的写请求,只读的slave并非为了防范不可信的客户端,毕竟一些管理命令例如DEBUGCONFIG在只读模式下仍是可使用的。若是确实要确保安全性,那么能够在配置文件中将一些命令从新命名。

也许你会感到很奇怪,为何可以将一个只读模式的slave恢复为可写的呢,尽管可写,可是只要slave一同步master的数据,就会丢失那些写在slave的数据。不过仍是有一些合法的应用场景须要存储瞬时数据会用到这个特性。不过,以后可能会考虑废除掉这个特性。

Setting a slave to authenticate to a master

若是master经过requirepass配置项设置了密码,slave每次同步操做都须要验证密码,能够经过在slave的配置文件中添加如下配置项:

masterauth <password>

也能够经过客户端在运行时发送如下命令:

config set masterauth <password>

至少N个slave才容许向master写数据

从redis2.8版本开始,master能够被配置为,只有当master当前有至少N个slave链接着的时候才接受写数据的请求。

然而,因为redis是异步复制的,因此它并不能保证slave会受到一个写请求,因此总有一个数据丢失的时间窗口存在。

这个机制的工做原理以下所示:

  • slave每秒发送ping心跳给master,询问当前复制了多少数据。
  • master会记录下它上次收到某个slave的ping心跳是何时。
  • 使用者能够配置一个时间,来指定ping心跳的发送不该超过的一个超时时间

若是master有至少N个slave,而且ping心跳的超时不超过M秒,那么它就会接收写请求。

也许你会认为这情形好似CAP理论中弱化版的C(consistency),由于写请求并不能保证数据的一致性,但这样作,至少数据丢失被限制在了限定的时间内。即M秒。

若是N和M的条件都没法达到,那么master会回复一个错误信息。写请求也不会被处理。

有两个配置项用来配置上文中提到的N和M:

min-slaves-to-write <number of slaves>
    min-slaves-max-lag <number of seconds>

若是须要了解更多,请查阅redis.conf配置文件。

扫一扫关注个人微信公众号

相关文章
相关标签/搜索