浅析Redis复制

摘要

早期的RDBMS被设计为运行在单个CPU之上,读写操做都由经单个数据库实例完成,复制技术使得数据库的读写操做能够分散在运行于不一样CPU之上的独立服务器上,Redis做为一个开源的、优秀的key-value缓存及持久化存储解决方案,也提供了复制功能,本文主要介绍Redis的复制原理及特性。redis

Redis复制概论

数据库复制指的是发生在不一样数据库实例之间,单向的信息传播的行为,一般由被复制方和复制方组成,被复制方和复制方之间创建网络链接,复制方式一般为被复制方主动将数据发送到复制方,复制方接收到数据存储在当前实例,最终目的是为了保证双方的数据一致、同步。数据库

复制示意图编程

Redis复制方式

Redis的复制方式有两种,一种是主(master)-从(slave)模式,一种是从(slave)-从(slave)模式,所以Redis的复制拓扑图会丰富一些,能够像星型拓扑,也能够像个有向无环:缓存

Redis集群复制结构图安全

经过配置多个Redis实例独立运行、定向复制,造成Redis集群,master负责写、slave负责读。服务器

复制优势

经过配置多个Redis实例,数据备份在不一样的实例上,主库专一写请求,从库负责读请求,这样的好处主要体如今下面几个方面:网络

一、高可用性

在一个Redis集群中,若是master宕机,slave能够介入并取代master的位置,所以对于整个Redis服务来讲不至于提供不了服务,这样使得整个Redis服务足够安全。less

二、高性能

在一个Redis集群中,master负责写请求,slave负责读请求,这么作一方面经过将读请求分散到其余机器从而大大减小了master服务器的压力,另外一方面slave专一于提供读服务从而提升了响应和读取速度。异步

三、水平扩展性

经过增长slave机器能够横向(水平)扩展Redis服务的整个查询服务的能力。分布式

复制缺点

复制提供了高可用性的解决方案,但同时引入了分布式计算的复杂度问题,认为有两个核心问题:

  1. 数据一致性问题,如何保证master服务器写入的数据可以及时同步到slave机器上。
  2. 编程复杂,如何在客户端提供读写分离的实现方案,经过客户端实现将读写请求分别路由到master和slave实例上。

上面两个问题,尤为是第一个问题是Redis服务实现一直在演变,致力于解决的一个问题。

复制实时性和数据一致性矛盾

Redis提供了提升数据一致性的解决方案,本文后面会进行介绍,一致性程度的增长虽然使得我可以更信任数据,可是更好的一致性方案一般伴随着性能的损失,从而减小了吞吐量和服务能力。然而咱们但愿系统的性能达到最优,则必需要牺牲一致性的程度,所以Redis的复制实时性和数据一致性是存在矛盾的。

Redis复制原理及特性

slave指向master

举个例子,咱们有四台redis实例,M1,R一、R二、R3,其中M1为master,R一、R二、R3分别为三台slave redis实例。在M1启动以下:

./redis-server ../redis8000.conf --port 8000

下面分别为R一、R二、R3的启动命令:

./redis-server ../redis8001.conf --port 8001 --slaveof 127.0.0.1 8000
 ./redis-server ../redis8002.conf --port 8002 --slaveof 127.0.0.1 8000
 ./redis-server ../redis8003.conf --port 8003 --slaveof 127.0.0.1 8000

这样,咱们就成功的启动了四台Redis实例,master实例的服务端口为8000,R一、R二、R3的服务端口分别为800一、800二、8003,集群图以下:

Redis集群复制拓扑

上面的命令在slave启动的时候就指定了master机器,咱们也能够在slave运行的时候经过slaveof命令来指定master机器。

复制过程

Redis复制主要由SYNC命令实现,复制过程以下图:

Redis复制过程

上图为Redis复制工做过程:

  1. slave向master发送sync命令。
  2. master开启子进程来说dataset写入rdb文件,同时将子进程完成以前接收到的写命令缓存起来。
  3. 子进程写完,父进程得知,开始将RDB文件发送给slave。
  4. master发送完RDB文件,将缓存的命令也发给slave。
  5. master增量的把写命令发给slave。

值得注意的是,当slave跟master的链接断开时,slave能够自动的从新链接master,在redis2.8版本以前,每当slave进程挂掉从新链接master的时候都会开始新的一轮全量复制。若是master同时接收到多个slave的同步请求,则master只须要备份一次RDB文件。

增量复制

上面复制过程介绍的最后提到,slave和master断开了、当slave和master从新链接上以后须要全量复制,这个策略是很不友好的,从Redis2.8开始,Redis提供了增量复制的机制:

增量复制机制

master除了备份RDB文件以外还会维护者一个环形队列,以及环形队列的写索引和slave同步的全局offset,环形队列用于存储最新的操做数据,当slave和maste断开重连以后,会把slave维护的offset,也就是上一次同步到哪里的这个值告诉master,同时会告诉master上次和当前slave链接的master的runid,知足下面两个条件,Redis不会全量复制:

  1. slave传递的run id和master的run id一致。
  2. master在环形队列上能够找到对呀offset的值。

知足上面两个条件,Redis就不会全量复制,这样的好处是大大的提升的性能,不作无效的功。

增量复制是由psync命令实现的,slave能够经过psync命令来让Redis进行增量复制,固然最终是否可以增量复制取决于环形队列的大小和slave的断线时间长短和重连的这个master是不是以前的master。

环形队列大小配置参数:

repl-backlog-size 1mb

Redis同时也提供了当没有slave须要同步的时候,多久能够释放环形队列:

repl-backlog-ttl 3600

免持久化复制

免持久化机制官方叫作Diskless Replication,前面基于RDB文件写磁盘的方式能够看出,Redis必需要先将RDB文件写入磁盘,才进行网络传输,那么为何不能直接经过网络把RDB文件传送给slave呢?免持久化复制就是作这个事情的,并且在Redis2.8.18版本开始支持,固然目前仍是实验阶段。

值得注意的是,一旦基于Diskless Replication的复制传送开始,新的slave请求须要等待此次传输完毕才可以获得服务。

是否开启Diskless Replication的开关配置为:

repo-diskless-sync no

为了让后续的slave可以尽可能遇上本次复制,Redis提供了一个参数配置指定复制开始的时间延迟:

repl-diskless-sync-delay 5

slave只读模式

自从Redis2.6版本开始,支持对slave的只读模式的配置,默认对slave的配置也是只读。只读模式的slave将会拒绝客户端的写请求,从而避免由于从slave写入而致使的数据不一致问题。

半同步复制

和MySQL复制策略有点相似,Redis复制自己是异步的,但也提供了半同步的复制策略,半同步复制策略在Redis复制中的语义是这样的:

容许用户给出这样的配置:在maste接受写操做的时候,只有当必定时间间隔内,至少有N台slave在线,不然写入无效。

上面功能的实现基于Redis下面特性:

  1. Redis slaves每秒钟会ping一次master,告诉master当前slave复制到哪里了。
  2. Redis master会记住每一个slave复制到哪里了。

咱们能够经过下面配置来指定时间间隔和N这个值:

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

当配置了上面两个参数以后,一旦对于一个写操做没有知足上面的两个条件,则master会报错,而且将本次写操做视为无效。这有点像CAP理论中的“C”,即一致性实现,虽然半同步策略不可以彻底保证master和slave的数据一致性,可是相对减小了不一致性的窗口期。

总结

本文在理解Redis复制概念和复制的优缺点的基础之上介绍了当前Redis复制工做原理以及主要特性,但愿可以帮助你们。

相关文章
相关标签/搜索