Redis主从

Posted 架构师成长

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis主从相关的知识,希望对你有一定的参考价值。

Redis单节点存在单点故障问题,为了解决单点问题,一般都需要对redis配置从节点,然后使用哨兵来监听主节点的存活状态,如果主节点挂掉,从节点能继续提供缓存功能。

主从配置结合哨兵模式能解决单点故障问题,提高redis可用性。从节点仅提供读操作,主节点提供写操作来实现读写分离。对于读多写少的状况,可给主节点配置多个从节点,从而提高响应效率。


主从复制过程

1. 从节点执行slaveof[masterIP][masterPort](从节点配置文件中配置slaveof),保存主节点信息。

2. 从节点中的定时任务发现主节点信息,建立和主节点的socket连接。

3. 从节点发送Ping信号,主节点返回Pong,两边能互相通信。

4. 连接建立后,主节点将所有数据发送给从节点(快照同步,rdb方式),从节点接受到rdb文件后,清空自己的数据,然后重新加载RDB到自己的内存中,在这个过程中基于旧的数据对外提供服务如果主节点开启了AOF,那么在快照同步结束后会立即执行BGREWRITEAOF,重写AOF文件。

5. 主节点把当前的数据同步给从节点后,便完成了复制的建立过程。主从节点进行快照同步的时候,主节点会把接收到的新请求命令写在缓存 buffer 中,当快照同步完成后,再把 buffer 中的指令增量同步到从节点。接下来,主节点就会持续的把写命令发送给从节点,保证主从数据一致性。


主节点维护了一个backlog文件,默认是1MB大小,主节点向从节点发送全量数据(RDB文件)时,也会同步往backlog中写,这样当发送全量数据这个过程意外中断后,从backlog文件中可以得知数据有哪些是发送成功了,哪些还没有发送,然后当主从节点再次连接后,从失败的地方开始增量同步。这里需要注意的是,当快照同步连接中断后,主从节点再次连接并非是第一次连接,所以进行增量同步,而不是继续进行快照同步。


主从节点都会维护一个offset,随着主节点的数据变化以及主从同步的进行,主从节点会不断累加自己维护的offset,从节点每秒都会上报自己的offset给主节点,主节点也会保存每个从节点的offset,这样主从节点就能知道互相之间的数据一致性情况。从节点发送psync runid offset命令给主节点从而开始主从同步,主节点会根据自身的情况返回响应信息,可能是FULLRESYNC runid offset触发全量复制,也可能是CONTINUE触发增量复制。


建议在主节点使用AOF+RDB的持久化方式,并且在主节点定期备份RDB文件,而从节点不要开启AOF机制,只开启RDB,原因有两个,一是从节点AOF会降低性能,二是如果主节点数据丢失,主节点数据同步给从节点后,从节点收到了空的数据,如果开启了AOF,会生成空的AOF文件,基于AOF恢复数据后,全部数据就都丢失了,而如果不开启AOF机制,从节点启动后,基于自身的RDB文件恢复数据,这样不至于丢失全部数据。


主从数据同步

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。


具体流程:

1. 主节点发送数据给从节点过程中,主节点还会进行一些写操作,这时候的数据存储在复制缓冲区中。从节点同步主节点数据完成后,主节点将缓冲区的数据继续发送给从节点,用于部分复制。

2. 主节点响应写命令时,不但会把命令发送给从节点,还会写入复制积压缓冲区(backlog),用于复制命令丢失的数据补救。



上面是psync的执行流程:从节点发送psync[runId][offset]命令,主节点有三种响应:(1)FULLRESYNC:第一次连接,进行全量复制 。

(2)CONTINUE:进行部分增量复制

(3)ERR:不支持psync命令,进行全量复制


全量复制:

1、从节点发送psync ? -1命令(因为第一次发送,不知道主节点的runId,所以为?,因为是第一次复制,所以offset=-1)。

2、主节点发现从节点是第一次复制,返回FULLRESYNC {runId} {offset},runId是主节点的runId,offset是主节点目前的offset。

3、从节点接收主节点信息后,保存到info中。

4、主节点在发送FULLRESYNC后,启动bgsave命令,生成RDB文件(数据持久化)。

5、主节点发送RDB文件给从节点。到从节点加载数据完成这段期间主节点的写命令放入缓冲区。

6、从节点清理自己的数据库数据。

7、从节点加载RDB文件,将数据保存到自己的数据库中。

8、如果从节点开启了AOF,从节点会异步重写AOF文件。


关于部分复制有以下几点说明:

1、部分复制主要是Redis针对全量复制的过高开销做出的一种优化措施,使用psync[runId][offset]命令实现。当从节点正在复制主节点时,如果出现网络闪断或者命令丢失等异常情况时,从节点会向主节点要求补发丢失的命令数据,主节点的复制积压缓冲区将这部分数据直接发送给从节点,这样就可以保持主从节点复制的一致性。补发的这部分数据一般远远小于全量数据。

2、主从连接中断期间主节点依然响应命令,但因复制连接中断命令无法发送给从节点,不过主节点内的复制积压缓冲区依然可以保存最近一段时间的写命令数据。

3、当主从连接恢复后,由于从节点之前保存了自身已复制的偏移量和主节点的运行ID。因此会把它们当做psync参数发送给主节点,要求进行部分复制。

4、主节点接收到psync命令后首先核对参数runId是否与自身一致,如果一致,说明之前复制的是当前主节点;之后根据参数offset在复制积压缓冲区中查找,如果offset之后的数据存在,则对从节点发送+COUTINUE命令,表示可以进行部分复制。因为缓冲区大小固定,若发生缓冲溢出,则进行全量复制。

5、主节点根据偏移量把复制积压缓冲区里的数据发送给从节点,保证主从复制进入正常状态。


以上是关于Redis主从的主要内容,如果未能解决你的问题,请参考以下文章

Redis主从与哨兵架构详解 Redis主从架构 如何在同一台机器搭建主从架构 Redis主从工作原理 数据部分复制 Jedis使用 Redis的管道(Pipeline) Redis Lua脚本(代码

redis主从配置及主从切换

【redis】redis 手动切换主从

redis优化系列Redis主从原理主从常用配置

Redis数据库——(主从复制哨兵模式集群)

redis高可用之主从复制,哨兵,集群