Redis是一个开源的key value存储系统,受到了广大互联网公司的青睐。Redis3.0版本之前只支持单节点运行模式,在3.0版本及以后才支持集群。
虽然Redis有持久化功能,能够保障redis服务器宕机也能恢复并且只有少量数据丢失(不建议使用redis来做持久化的处理),但是由于所有数据在一台服务器上,如果这台服务器出现硬盘故障,那就算是有备份也仍然不可避免数据丢失的问题。
在实际生产环境中,我们不可能使用一台redis服务器来作为我们的缓存服务器,所以为了避免单点故障问题,必须要使用多台服务器来实现Redis集群。[如需了解Redis集群安装,请移步:Redis-5.0.3集群安装]
主从复制(数据同步)
主从复制,可以实现当一台Redis服务器的数据更新后,自动将新的数据同步到集群中的其他服务器上,从而保证数据一致,主要用来解决Redis集群多节点之间数据的同步问题。
Redis集群的出现,能够解决①单点故障的问题的同时,也能够实现②读写分离的操作(master负责写,slave负责读)
原理
Redis的主从复制可以确保Redis集群的master和slave之间的数据同步。主从复制可以分为①全量复制和②增量复制,在Redis2.8版本之后,引入了③无磁盘复制。本文将对这三种复制进行简单的理解。
1.全量复制
Redis的全量复制,一般发生在slave节点初始化阶段。这时候slave节点需要将master节点上的所有数据都复制一份,详细步骤如下图所示。(基于RDB快照方式)

完成上图步骤,即完成了slave节点数据初始化的所有操作,slave节点此时便可以接受来自用户的读请求操作。Redis集群中的master/slave的复制策略采用的是乐观复制,也就是说可以容忍在一定时间内master/slave数据的内容是不同的,但是两者的数据都会最终同步一致的。
为什么在一段时间内master/slave数据的内容是不同的呢?因为Redis的主从复制同步过程是异步操作的,即:master执行完客户端请求命令后,会立即将结果返回给客户端,然后再异步将命令同步给slave,从而导致master/slave节点在短时间内的数据不一致性。切记:Redis遵循的是弱一致性原则。
为什么要采用异步操作呢?因为Redis是基于内存的一个非关系型数据库,性能是非常快的,如果使用同步操作,可能会对Redis的性能有所影响,所以此处使用异步操作,可以保证Redis集群的性能不受影响。
你可能有疑惑,如果在数据不一致期间,master/slave节点因为网络问题等导致连接断开,而这个时候,master是无法得知某个写命令是否最终同步给了多少个slave节点。此时Redis提供了一个配置项来限制master是否可写,即:只有master数据至少同步给多少个slave节点时,master节点才是可写的。我们可以在redis.conf配置文件中查看。zhi
//表示只有当3个或以上的slave连接到master,master才是可写的
min-slaves-to-write 3
//表示允许slave最长失去连接的时间,如果10秒还没有收到slave的响应,则master认为该slave已断开
min-slaves-max-lag 10
2.增量复制
Redis2.8版本开始,支持主从复制的断点续传,如果主从复制过程中,网络连接断开了,那么可以接着上次复制的地方,继续复制下去,而不是从头开始复制。详细步骤如下图所示。
master节点会在内存中创建一个backlog,master和slave会保存一个replica offset,还有一个master replid,offset就是保存在backlog中。如果master和slave网络连接断开了,slave会让master从上次的replica offset处开始复制。如果没有找到对应的offset,那么变会执行全量复制操作。(如下图所示,为一主已从,我们能够发现offset,backlog,master_replid等都是相同的,说明已经同步完成)
3.无磁盘复制
Redis的全量复制,是基于RDB方式的持久化实现的,也就是master节点在后台保存RDB快照,slave节点接收到rdb文件,然后载入,完成复制操作。但是这种方式也会存在如下一些问题:
①当master节点禁用RDB方式,如果执行复制初始化操作,Redis依然会生成RDB快照,当master节点下次启动时,执行该rdb文件的恢复,因为复制发生的时间点不确定,导致恢复的数据的时间点也不确定,可能是任何时间点的,从而导致数据出现问题;
②当磁盘性能差,复制是存在性能过慢等问题,那么初始化复制过程,便会对性能产生比较大的影响。
基于以上问题,Redis在2.8.18以后的版本,引入了无硬盘复制这一选项,可以在不需要磁盘中的rdb文件去同步,直接在内存中创建一个rdb文件,直接发送数据至slave节点。在redis.conf配置文件中,通过以下配置来开启该功能:
//开启无硬盘复制,默认为no 不开启
repl-diskless-sync yes
至此,Redis集群主从复制,数据一致性原理讲解完毕
END