摘要:Redis在主从模式下会有许多问题需要考虑,这里写了一些关于redis在多服务器下的一些问题分析和总结。
Redis单节点存在单点故障问题,为了解决单点问题,一般都需要对redis配置从节点,然后使用哨兵来监听主节点的存活状态,如果主节点挂掉,从节点能继续提供缓存功能。主从配置结合哨兵模式能解决单点故障问题,提高redis可用性。从节点仅提供读操作,主节点提供写操作。对于读多写少的状况,可给主节点配置多个从节点,从而提高响应效率。
主从复制过程:从节点执行slaveof[masterIP][masterPort],保存主节点信息
从节点中的定时任务发现主节点信息,建立和主节点的socket连接
从节点发送Ping信号,主节点返回Pong,两边能互相通信
主节点把当前的数据同步给从节点后,便完成了复制的建立过程。接下来,主节点就会持续的把写命令发送给从节点,保证主从数据一致性。
Redis的数据同步过程:redis2.8之前使用sync[runId][offset]同步命令,redis2.8之后使用psync[runId][offset]命令。
两者不同在于,sync命令仅支持全量复制过程,psync支持全量和部分复制。
介绍同步之前,先介绍几个概念:
runId:每个redis节点启动都会生成唯一的uuid,每次redis重启后,runId都会发生变化。
offset:主节点和从节点都各自维护自己的主从复制偏移量offset,当主节点有写入命令时,offset=offset+命令的字节长度。从节点在收到主节点发送的命令后,也会增加自己的offset,并把自己的offset发送给主节点。这样,主节点同时保存自己的offset和从节点的offset,通过对比offset来判断主从节点数据是否一致。
repl_backlog_size:保存在主节点上的一个固定长度的先进先出队列,默认大小是1MB。
主节点发送数据给从节点过程中,主节点还会进行一些写操作,这时候的数据存储在复制缓冲区中。从节点同步主节点数据完成后,主节点将缓冲区的数据继续发送给从节点,用于部分复制。
主节点响应写命令时,不但会把命名发送给从节点,还会写入复制积压缓冲区,用于复制命令丢失的数据补救。
上面是psync的执行流程:
从节点发送psync[runId][offset]命令,主节点有三种响应:
FULLRESYNC:第一次连接,进行全量复制
CONTINUE:进行部分复制
ERR:不支持psync命令,进行全量复制
全量复制和部分复制的过程
上面是全量复制的流程。主要有以下几步:
从节点发送psync ? -1命令(因为第一次发送,不知道主节点的runId,所以为?,因为是第一次复制,所以offset=-1)。
主节点发现从节点是第一次复制,返回FULLRESYNC {runId} {offset},runId是主节点的runId,offset是主节点目前的offset。
从节点接收主节点信息后,保存到info中。
主节点在发送FULLRESYNC后,启动bgsave命令,生成RDB文件(数据持久化)。
主节点发送RDB文件给从节点。到从节点加载数据完成这段期间主节点的写命令放入缓冲区。
从节点清理自己的数据库数据。
从节点加载RDB文件,将数据保存到自己的数据库中。-如果从节点开启了AOF,从节点会异步重写AOF文件。
关于部分复制有以下几点说明:部分复制主要是Redis针对全量复制的过高开销做出的一种优化措施,使用psync[runId][offset]命令实现。当从节点正在复制主节点时,如果出现网络闪断或者命令丢失等异常情况时,从节点会向主节点要求补发丢失的命令数据,主节点的复制积压缓冲区将这部分数据直接发送给从节点,这样就可以保持主从节点复制的一致性。补发的这部分数据一般远远小于全量数据。
主从连接中断期间主节点依然响应命令,但因复制连接中断命令无法发送给从节点,不过主节点内的复制积压缓冲区依然可以保存最近一段时间的写命令数据。
当主从连接恢复后,由于从节点之前保存了自身已复制的偏移量和主节点的运行ID。因此会把它们当做psync参数发送给主节点,要求进行部分复制。