主从复制的作用
我们知道Redis是一个高性能的缓存中间件,一个Redis实例可以支撑几万的并发请求。
但是在一些超高的并发场景下,比如上百万以上的并发查询请求,虽然Redis读写速度很快,但是也会产生读压力过大的情况。
为了分担读的压力,可以搭建Redis主从架构。主节点可以进行读写,从节点只对外提供读的功能。从节点的数据是从主节点同步过来。
主从复制的特点:
- 主节点对外提供读写功能
- 从节点只对外提供读功能,也可以不提供,只做数据备份
搭建过程
这里以虚拟机 CentOS7 + Redis5 为例。
首先在虚拟机上安装3个Redis实例,安装过程见CentOS7 安装 Redis全过程
这三个Redis的端口分别为: 6379, 6380, 6381
安装完成后,虚拟机上则运行了三个Redis实例:
现在我们要将运行在6379端口的Redis作为Master, 6380,6381作为Slave,一主二从
我们需要修改从节点的配置文件,先修改6380的
vi /etc/redis/6380.conf
在配置文件中配置replicaof 项,配置为主节点的IP和端口号
replicaof 192.168.164.156 6379
同样,在6381的配置文件中也做同样的修改
vi /etc/redis/6381.conf
replicaof 192.168.164.156 6379
这两个配置文件修改完成后,重启对应的Redis实例即可。
service redis_6380 restart
service redis_6381 restart
验证
重启完成后,下面来进行验证主从复制是否生效。
分别连接到三个Redis实例,查看有无数据
6379:
6380:
6381:
可以看到在当前的3台Redis实例中,都没有数据。
如果主从搭建成功的话, 当我们往主节点写入数据时,那么数据会同步到从节点,从节点也应该可以查到写入的数据。
我们向主节点中写入一条数据。
然后分别在两个从节点中查看
可以看到,在两个从节点中已经有数据了。
到这里说明主从复制搭建成功了。
另外,之前说道,从节点无法对外提供写操作,这里我们来验证一下。
可以看到,在从节点执行写操作时,会报如下错误。
(error) READONLY You can't write against a read only replica.
当然,也可以通过修改配置项 replica-read-only 为 no,让从机可以写入数据,但这会导致从节点的数据与主节点不一致。因为从节点的数据不会同步给主节点。所以一般不开启。
主从复制的原理
Redis主从复制可以分为全量同步和增量同步。
全量同步过程
全量同步一般是从节点第一次连接上主节点,或者是从节点宕机过长时间而采用的数据同步方式。
当Slave连接上Master后,会发送一个PSYNC 命令给Master请求复制数据。 Master收到PSYNC命令后,会在后台进行数据持久化通过bgsave命令生成最新的RDB快照文件,持久化期间,Master会继续接收客户端的请求,它会把这些可能修改数据集的请求缓存在内存中。当持久化进行完毕以后,Master会把这份RDB文件发送给Slave,Slave会把接收到的数据进行持久化生成RDB,然后再加载到内存中。之后,Master再将之前缓存在内存中的命令发送给Slave。 当Master与Slave之间的连接由于某些原因而断开时,Slave能够自动重连Master,如果Master收到了多 个Slave并发连接请求,它只会进行一次持久化,而不是一个连接一次,然后再把这一份持久化的数据发送 给多个并发连接的Slave。
值得注意的是,这里生成的RDB文件和是否开启RDB持久化没有任何关系,即使没有开启RDB持久化方式,这里也同样会生成RDB快照发送给Slave。
replication_buffer:replication buffer里面存放的数据是从Master生成RDB快照之后到Slave完成加载收到的RDB文件时间之间,所有的master数据更新操作。buffer占用的是内存空间,如果持续增大buffer的大小,会消耗大量的内存资源,所以redis提供了断开这个client的连接,通过 “client-output-buffer-limit”,可以设置限制,当从库处理慢导致主库内存buffer到达限制后,主库会强制断开从库的连接。
配置的格式为:
client-output-buffer-limit <class> <hard limit> <soft limit> <soft seconds>
具体参数含义:
-
class: 客户端种类,包括normal,replica,pubsub
- normal:普通的客户端。默认limit 是0,也就是不限制 - replica:从库的复制客户端。默认hard limit 256M,soft limit 64M/60s - pubsub:布与订阅的客户端。默认hard limit 32M,soft limit 8M/60s
-
hard limit:缓冲区大小的硬性限制
-
soft limit:缓冲区大小的软性限制
-
soft seconds:缓冲区大小达到了soft limit值的持续时间。
增量同步过程
当Master和Slave断开重连后,一般都会对整份数据进行复制。但从redis2.8版本开始,redis改用可以支 持部分数据复制的命令PSYNC去Master同步数据,Slave与Master能够在网络连接断开重连后只进行部分 数据复制(断点续传)。 Master会在其内存中创建一个复制数据用的缓存队列,缓存最近一段时间的数据,Master和它所有的 Slave都维护了复制的数据下标offset和Master的进程id,因此,当网络连接断开后,Slave会请求Master 继续进行未完成的复制,从所记录的数据下标开始。如果Master进程id变化了,或者从节点数据下标 offset太旧,已经不在Master的缓存队列里了,那么将会进行一次全量数据的复制。
repl_backlog_buffer: 为了解决从库断连后找不到主从差异数据而设立的环形缓冲区,从而避免全量同步带来的性能开销。在redis.conf配置文件中可以设置大小,如果从库断开时间过长,repl_backlog_buffer环形缓冲区会被主库的写命令覆盖,那么从库重连后只能全量同步,所以repl_backlog_size配置尽量大一点可以降低从库连接后全量同步的频率。
主从复制风暴
如果一个Redis主节点有很多个从节点,那么可能会导致多个从节点同时复制主节点而使主节点压力过大,进而引发问题。这就是主从复制风暴。
解决主从复制风暴,可以搭建树状主从架构,来分担主节点的压力。
主从复制的缺点
- 从节点无法对外提供写功能,那么主节点挂后,就无法再向Redis中写入数据了
- 主从复制只是用来分担读的压力,无法满足高可用
- 当主节点故障时,需手动将一个从节点晋升为主节点,业务方也需变更配置,并且需要修改其他从节点的配置,整个过程需要人为干预,比较繁琐
- 主库的写能力和存储能力受到单机的限制,因为主从架构中每一个Redis实例存储的都是全量的数据
主从复制虽然为单个Redis节点分担了读的压力,但是主从架构还是存在着一些缺点,导致在真实生产环境中,用的并不多。但是主从架构是后续Redis高可用架构的基石。包括Redis的哨兵机制和Redis Cluster 都是以主从为基础进行扩展的。