1. 认识主从复制
1. 单机部署Redis的问题:首先是如果机器故障(突然断电或者机器宕机),那么数据就会大量丢失;其次就是单机Redis的容量会有瓶颈,受限于机器的内存空间;每秒的请求处理数也会受到单机Redis的限制,尽管Redis每秒的请求处理数可以很高,但在大型应用中仍然是远远不够的。为了解决这些问题,实现高可用,Redis提供了一个主从复制的功能,来实现集群式部署Redis
2. 简单了解主从复制的模型:主从复制,会有一个主节点和多个从节点,每一个节点都是一个Redis,而且每一个Redis节点都能给客户端提供Redis的服务,主从复制就是从主Redis节点中复制数据到从Redis节点,如果主节点进行一个数据更新操作,那么从节点也会进行一个相同的操作。主从复制通过RDB文件来实现。
3. 主从复制的作用:
- 数据副本:避免单机部署中机器故障造成的数据丢失,而且如果主节点宕机,从节点就会提供支援代替主节点向客户端提供服务。
- 扩展性能:读写操作分离,大量的对主节点进行读写操作会造成很大的性能负担,可以将读操作分流到多个从节点中,这样就可以极大的提升读操作的性能。
4. 主从复制的特点:
- 只能一个主节点对于多个从节点,一对多的关系
- 数据只能从主节点复制到从节点,数据流是单向的
2. 主从复制的实现配置
1. 有两种实现方式:分别是通过运行命令来实现,另一种是通过redis的启动配置文件来实现
- slaveof命令:
- 变为从节点:使用形式为slaveof masterip masterport,需要指定当前从节点Redis的主节点Redis的ip地址masterip和端口号masterport,执行该命令后,就会通过网络连接到指定的主节点,并通过网络传输进行数据复制,数据复制是异步操作;另外,如果从节点中之前存储有数据,那么在变成从节点之后就会清空之前保存的数据
- 变为主节点:使用形式为slaveof no one,会取消自己与主节点的主从关系,但不会删除之前复制的数据
- 通过从节点Redis的启动配置文件修改配置参数:
- slaveof masterip masterport:需要指定主节点Redis所在机器的IP地址masterip 和运行时占用的端口号masterport
- slave-read-only yes:该配置参数表示当前从节点是否只允许进行读操作,默认yes表示只能进行读操作(不建议修改),该配置参数保证了当前Redis节点被配置为从节点之后,不会执行写操作,防止主从节点之间的数据不同步
3. 主从复制的实现方式——全量复制功能
1. run_id:Redis每次启动时,都会生成一个不同的id来标示当前运行的Redis。从节点中会保存主节点的run_id标示,如果主节点的Redis发生了重启,那么从节点依据ip和端口号连接到主节点时,就会发现主节点的run_id标示的改变(这种改变意味着主节点中的数据可能发生的大量的改动),所以此时就会引起全量复制,也就是将主节点中的所有数据全部复制过来。
2. 偏移量:每当主节点增删改一个数据时,主节点中就会有一个数值来记录这种变化,偏移量就是记录Redis中数据改变的一个标示,当主节点更改一个数据时,偏移量也会发生对应的改变,而且主节点在将数据更改命令同步给从节点时,也会将该偏移量发送给从节点,这样就可以对比主从节点的偏移量,来观察是否出现主从不一致的问题。下图中master_repl_offset就表示主节点的偏移量,高亮处就表示从节点中的偏移量,使用 ./redis-cli -p 6379 info replication 该命令即可在主节点中查看主从节点的偏移量
3. 全量复制:全量复制指的是不仅仅复制主节点发送过来的RDB文件中的数据,还要将主节点在生成RDB文件期间主节点后续执行的数据更改命令所更改的数据一并复制过来,在这期间,主节点执行的数据更改命令会被记录在一个缓冲区repl_back_buffer中,当从节点RDB加载完毕后,就会将这一部分被更改的数据同步到从节点中,具体过程如下
- 当从节点执行slaveof命令时,就会自动向主节点发送一条命令(psync ? -1),第一个参数表示主节点的run_id,第二个参数表示当前从节点的偏移量为-1,然后从节点就会接收到主节点返回的主节点的run_id和偏移量等信息并保存
- 主节点自动执行bgsave命令生成RDB文件,在此期间会记录后续执行的数据更改命令所更改的数据,直到主节点将生成的RDB文件传输到从节点为止
- 主节点发送RDB文件,从节点接收完毕后,主节点会将缓冲区中记录的新更改的数据发送给从节点,从节点再接收
- 从节点清空此前的所有数据,加载RDB文件恢复数据并存入新更改的数据
4. 全量复制的性能开销:主要消耗在主节点RDB文件的生成需要的时间,其次是RDB文件在网络间的传输时间,还需要从节点的数据清空时间、加载RDB文件的时间
5. 数据更改命令缓冲区repl_back_buffer用于:当Redis通过Linux中的fork()函数开辟一个子进程处理其他事务(比如主进程执行bgsave生成一个RDB文件时,或者主进程执行bgrewriteaof生成一个AOF文件时),而主进程(即处理客户端命令的进程)后续执行的一些数据更改命令会被暂时保存在该区域,而且该区域空间有限(配置文件中repl-backlog-size 1mb即可配置该处空间大小)
4. 主从复制的实现方式——部分复制功能
1. 部分复制解决的问题:在实际环境中,主节点与从节点之间可能会发生一些网络波动等情况,导致从节点与主节点之间的网络连接断开(主从节点的Redis均未关闭),如果重新连接上后,可以使用全量复制来重新进行一次主从节点数据同步,但是全量复制会带来一个性能开销的问题,而且从节点中可能有大量数据是主节点中没有更该过的,也就是不需要进行再次同步的数据,如果使用全量复制肯定是带来了一些不必要的浪费。所以,部分复制功能就是为了解决该问题的。
2. 部分复制的发生过程:
- 主从节点直接连接断开,此时主节点继续执行的数据更改命令会被记录在一个缓冲区repl_back_buffer中
- 当从节点重新连接主节点时,就会自动发出一条命令(psync offset runid),将从节点中存储的主节点的Redis运行时id和从节点中保存的偏移量发送给主节点
- 主节点接收从节点发送的偏移量和id,对比此时主节点的偏移量和接收的偏移量,如果两个偏移量之差大于repl_back_buffer中的数据,那么就表示在断开连接期间从节点已经丢失了超出规定数量的数据,此时就需要进行全量复制了,否则就进行部分复制
- 将主节点缓冲区中的数据同步更新到从节点中,这样就实现了部分数据的复制同步,降低了性能开销
5. 主从节点之间的故障维护
1. 故障发生时服务自动转移(自动故障转移):即当某个节点发生故障导致停止服务时,该节点提供的服务会有另一个节点自动代替提供,这样就实现了一个高可用的效果
2. 从节点故障:即如果某个从节点发生了故障,导致无法向在该节点上的客户端提供读服务,解决办法就是使该客户端转移到另一个可用从节点上,但是在转移时,应该考虑该从节点能承受几个客户端的压力
3. 主节点故障:如果主节点发生故障,在使用主节点进行读写操作的客户端就无法使用了,而使用从节点只进行读操作的客户端还是可以继续使用的,解决办法就是从从节点中选一个节点更改为主节点,并且将原主节点的客户端连接到新的主节点上,然后通过该客户端将其他从节点连接到新的主节点中
4. 主从复制确实可以解决故障问题,但是主从复制不能实现自动故障转移,其必须要通过一些手动操作,而且非常麻烦,所以要实现自动故障转移还需要另一个功能,Redis中提供了sentinel功能来实现自动故障转移。
6. 主从复制常见问题
1. 读写分离:即客户端发来的读写命令分开,写命令交给主节点执行,读命令交给从节点执行,不仅减少了主节点的压力,而且增强了读操作的能力;但也会造成一些问题
- 但是主从节点之间数据复制造成的阻塞延迟也可能会导致主从不一致的情况,也就是主节点先进行了写操作,但可能因为数据复制造成的阻塞延迟,导致在从节点上进行的读操作获取的数据与主节点不一致
- 读取过期数据:主从复制会将带有过期时间的数据一并复制到从节点中,但是从节点是没有删除数据的能力的,即使是过期数据,所以主节点中的已经删除了过期数据,但是因为主从复制的阻塞延迟问题导致从节点中的过期数据没有删除,此时客户端就会读到一个过期数据
2. 主从配置不一致:造成的问题有
- 比如配置中的maxmemory参数如果配置不一致,比如主节点2Gb,从节点1Gb,那么就可能会导致数据丢失;以及一些其他配置问题
3. 规避全量复制:全量复制的性能开销较大,所以要尽量避免全量复制,
- 在第一次建立主从节点关系式一定会发生全量复制;可以适当减小Redis的maxmemory参数,这样可以使得RDB更快,或者选择在客户端操作低峰期进行,比如深夜
- 从节点中保存的主节点运行id不一致时也一定会发生全量复制(比如主节点的重启);可以通过故障转移来尽量避免
- 当主从节点的偏移量之差大于命令缓冲区repl_back_buffer中对应数据的偏移差时,也会发生全量复制,也就是上面的部分复制的复制过程中所说的;可以增大配置文件中repl-backlog-size即数据缓冲区可尽量避免
4. 规避复制风暴:
- 单主节点导致的复制风暴,即当主节点重启后,要向其所有的从节点都进行一次全量复制,这非常消耗性能;可以更换主从节点的结果,更换为类似树形的结构,一个主节点只与少量的从节点建立主从关系,而而这些主节点又与其他从节点构成主从关系,如下图所示
- 单主节点机器复制风暴:即如果过一台机器专门用来部署多个主节点,然后其他机器部署从节点,那么一旦主节点机器宕机重启,就会引起所有的主从节点之间的全量复制,造成非常大的性能开销;可以采用多台机器,分散部署主节点,或者使用自动故障转移来将某个从节点变为主节点实现一个高可用