Redis的主从复制
前言
关系数据库通常会使用一个主服务器向多个从服务器发送更新,并使用从服务器来处理所有的读请求,redis采用了同样方法来实现自己的复制特性。
简单总结起来就是:在接收到主服务器发送的数据初始副本之后,客户端每次主服务器进行写命令时,从服务器都会实时地得到更新。部署好主从服务器之后,客户端可以向任意的从服务器发送读请求。
本文主要介绍redis实现数据同步复制简单过程、新旧版本之间的对比、以及一些需要注意的细节,主要参考资料《redis实战》与《redis设计与实现》(有需要的同学可以私信或者评论)
一、旧版复制功能
redis 2.8以前采用的复制都为旧版复制,主要使用sync命令同步复制,sync存在很大的缺陷严重消耗主服务器的资源以及大量的网络连接资源。redis 2.8之后采用psync命令替代sync,解决完善这些缺陷,但在介绍新版复制功能之前,必须先介绍旧版复制过程,这样才能更好地形成对比。
1、复制功能的两种模式
同时复制过程分为同步sync与命令传播(command propagate),两个过程配合执行才能实现redis复制。
1)同步操作:
通过从服务器发送到sync命令给主服务器-------->主服务器生成rdb文件并发送给从服务器,同时发送保存所有写命令给从服务器------>从服务器清空之前数据并执行解释rdb文件------->保持数据一致(还需要命令传播过程才能保持一致)
2)命令传播操作:
主服务器的数据库状态被修改(主服务器执行写命令,修改数据库),导致主从服务器数据库不一致时,通过发送让主从服务器不一致的命令(主服务器接收到的新写命令)给从服务器并执行,让主从服务器的数据库重新回到一致状态。
比如初次同步完成后,主从服务器数据库中都已经存在k1-k5的键,处于数据一致的状态
之后,主服务器客户端发送del删除命令,删除k3键,导致主从服务器数据不一致
为了让主从服务器数据再次回到一致状态,主服务器向从服务器发送del命令,紧接着从服务器接收并执行。即可回到一致状态
2、配置选项前提
1)主从复制的前提不用多说,就是先正确配置redis主从服务器,主要通过slaveof ip port选项配置或者slaveof 命令。
2)保证主服务器的rdb+aof配置正确,特别是rdb中dbfilename选项与aof中的dir选项,两个文件路径对于redis是可写的
3、主从复制过程
文字简单总结描述:
1)slave会建立和master的连接,然后发送sync命令;
2)master都会启动一个后台进程执行bgsave命令,将数据快快照保存到文件中,同时master主进程会开始收集新的写命令并缓存起来;
3)后台进程完成写文件后,master发送文件给slave,slave将文件保存到磁盘上,然后加载到内存恢复数据库快照到slave上。
4)紧接着master就会把缓存命令转发给slave,后续的master收到的写命令也通过跟slave连接发送给slave;
5)如果master同时接收到多个slave发来的同步连接请求,只会启动一个进程来写数据库镜像,然后发送给所有slave。
也可以参考以下表,其中步骤1-4可以认为是sync同步操作,而步骤5即为命令传播模式
注意事项
1)从服务器在同步时,会清空所有数据,服务器在与主服务器进行初连接时,数据库中的所有数据都将丢失,替换成主服务器发送的数据。
2)redis不支持主主复制
3)主从复制不会阻塞master(不会阻塞master处理客户端请求),相反slave在初次同步数据时会阻塞不能处理客户端请求。
4)当多个从服务器尝试连接同一个主服务器的时候,就会出现以下两种情况:
一是:步骤3还未执行,所有从服务器都会接收到相同的快照文件和相同缓冲区写命令。
二是:步骤3正在执行或者已经执行完毕,当主服务器与较早的从服务器完成以上全部步骤之后,主服务器会新连接的从服务器重新依次执行1-5步骤。
在大部分情况下,redis会尽可能去减少复制所需要的工作,但是从服务器连接的时机不凑巧的话,只好多做一些外额外工作。
5)多个从服务器连接主服务器时候,同步数据可能会占用很大一部分的带宽,可能会导致其他请求难以到达主服务器。
4、sync命令的缺陷
主要是主从服务器断线后重复制,即处于命令传播阶段的主从服务器由于网络断开,从服务器一直尝试连接主服务器连接成功后,继续复制主服务器。如下过程在主从服务器断开后重新连接期间,主服务器继续执行三个set命令,导致从服务器连接后发送l sync命令,重新进行了“全量”复制过程,rdb文件中包含k1-k10089全部的键。
其中可以明显看出重新连接主服务器之后,sync命令创建包含k1-k10089的rdb文件。而事实上只需要再同步断线后的k10087-k10089即可。sync的“全同步”对于从服务来说是不必要的。
sync命令非常消耗资源,原因有三点:
1)主服务器执行bgsave命令生成rdb文件,这个生成过程会大量消耗主服务器资源(cpu、内存和磁盘i/o资源)
2)主服务器需要将自己生成的rbd发送给从从服务器,这个发送操作会消耗主从服务器大量的网络资源(带宽与流量)
3)接收到rdb文件你的从服务器需要载入rdb文件,载入期间从服务器会因为阻塞而导致没办法处理命令请求。
二、新版复制功能
为了解决旧版本中断线情况下sync低效问题,在redis 2.8之后使用psync命令代替sync命令执行复制同步操作,自然psync具备完整重同步和部分重同步模式
1)完整重同步:跟旧版复制基本是一致的,可以理解为“全量”复制。
2)部分重同步:在命令传播阶段,断线重复制只需要发送主服务器在断开期间执行的写命给从服务器即可,可以理解为“增量”复制。
断开连接后发送+continue回复,表示使用psync部分重同步,只需要同步k10087-10089即可,不需要生成rdb文件
相关流程图如下:
上一篇: InfluxDB因修改默认数据目录导致服务无法正常运行的问题(权限问题)
下一篇: 浅谈Linq查询