当redis服务器发生单点故障硬盘损坏时,无论是RDB还是AOF机制都无法回复数据,如果实现高可用性
主从复制,是指将一台redis服务器的数据,复制到其他的redis服务器,前者称为master服务器,后者称为从服务器,数据的复制是单向的只能由主服务器到从服务器
默认情况下。每台服务器都是主服务器,且一个主服务器可以有多个服务器(没有从服务器)但是一个从服务器只能有一个主服务器
主从复制的作用:数据冗余,故障恢复,负载均衡,高可用基石
1. 主从复制开始与关闭:
1:配置文件的方式,在配置文件redis.conf中加入:slaveof <masterIP> <masterport>
2:启动命令,redis-server启动命令后输入: --slaveof <masterIP> <masterport>
3:客户端命令,客户端执行slaveof <masterIP> <masterport>,则改redis示例成为从服务器
关闭复制:
在从服务器中输入:slaveof no one
2. 主从复制的三个阶段
2.1连接准备
- 从服务器保存主服务器的host与ip信息,异步发送slaveof命令直接返回ok,实际复制操作才刚开始进行
- 主从服务器建立socket连接,用于RDB文件,同步命令传播,从服务器作为主服务器的client
- 从服务器发送ping命令检查socket是否可用以及主服务器是否能正常处理请求,从服务器收到三种响应pong,超时,非pong结果
- 身份验证,如果从服务器的配置文件中设置了masterauth,主从服务器的密码必须相同才能通过验证
- 从服务器发送自身的host与ip信息给主服务器
2.2全量复制
- 全量复制是一个非常耗时的操作:
- 主服务器通过bgsave命令fork子进程进行RDB持久化,改过程是非常消耗CPU,内存(页面复制)硬盘IO资源的
- 主服务器通过网络将RDB文件发送给从服务器,对主服务器的带宽都会带来很大的消耗
- 从服务器清空老数据,载入新的RDB文件的过程是阻塞的,无法响应客户端的命令
2.2.1部分复制:
部分复制的原理:
复制偏移量:执行复制的双方--主服务器和从服务器会分别维护一个复制偏移量
- 主服务器每次向从服务器传播N个字节的数据时,就会将自己的复制偏移量的值加上N
- 从服务器每次收到主服务器传播来的N个字节数据时,就会将自己的复制偏移量的值加上N
- 如果主服务器处于一致状态,那么主从服务器的偏移量总是相同
- 反之,如果主从服务器两者的偏移量不相同,说明主从服务器并未处于一致状态
2.3 命令传播
在命令传播阶段,除了发送写命令主从服务器还维持着心跳机制:ping 和REPLCONF ACK
1:主服务器向从服务器发送PING命令:
每隔特定的时间,主服务器会向从服务器发送PING命令,这个PING命令的作用,主要是为了让从服务器进行超时判断,PING发送的频率由repl-ping-slave-period参数控制,单位是秒,默认值是10s
2: 从服务器向主服务器发送REPLCONF ACK 命令
在命令传播阶段,从节点会向主节点发送REPLCONF ACK命令。频率是每秒1次;命令格式为REPLCONF ACK{offset}其中offset指从节点保存的复制偏移量
REPLCONF ACK命令作用包括:
实时监测主从服务器网络状态,该命令会被主服务器用于复制时的判断,主服务器使用info replaction 可以看到从服务器的状态中的tag值,表示距离上次收到命令的时间间隔,正常情况下为0或1
检测命令丢失,从服务器发送自身的offset,主服务器会与自己的offset对比,如果从服务器的数据丢失(如网络丢失包)主服务器通过复制积压缓冲区推送缺失的数据,offset和复制积压缓冲区 不仅可以用于部分复制,也可以用于处于理命令丢失情形;区别于前者是在断线重连后进行的,而后者是在主从服务节点没有断线的情况下进行的
3.常见问题
3.1 数据延迟与不一致
a、优化主从节点之间的网络环境(如在同机房部署);
b、监控主从节点延迟(通过offset)判断,如果从节点延迟过大,通知应用不再通过该从节点读取数据;
c、Redis复制提供了slave-serve-stale-data参数,默认开启状态。如果开启则从节点依然响应所有命令。对于无法容忍不一致的应用场景可以设置no来关闭命令执行,此时从节点除了info和slaveof命令之外所有的命令只返回“SYNC with master in progress”信息。
3.2 数据过期问题
在主从复制场景下,为了主从节点的数据一致性,从节点不会主动删除数据,而是由主节点控制从节点中过期数据的删除。由于主节点的惰性删除和定期删除策略,都不能保证主节点及时对过期数据执行删除操作,很容易读取到已经过期的数据。Redis 3.2中,从节点在读取数据时,增加了对数据是否过期的判断:如果该数据已过期,则不返回给客户端;将Redis升级到3.2可以解决数据过期问题。
3.2 故障转移
当主节点或从节点出现问题而发生更改时,需要及时修改应用程序读写Redis数据的连接;连接的切换可以手动进行,或者自己写监控程序进行切换,但前者响应慢、容易出错,后者实现复杂,成本都不算低。可以使用哨兵机制实现自动故障转移。
3.3 复制超时
注意Redis单机数据量不要过大,另一方面就是适当增大repl-timeout值,具体的大小可以根据bgsave耗时来调整。
主节点会向从节点发送PING命令,频率由repl-ping-slave-period控制;该参数应明显小于repl-timeout值(后者至少是前者的几倍)。否则,如果两个参数相等或接近,网络抖动导致个别PING命令丢失,此时恰巧主节点也没有向从节点发送数据,则从节点很容易判断超时。
3.4 输出缓冲区溢出
通过client-output-buffer-limit调整输出缓冲区的大小避免复制失败