面试题答案
一键面试Redis主从复制工作原理
- 建立连接:从节点通过
SLAVEOF
命令(或配置文件设置)向主节点发送同步请求,主节点接收到请求后,会为从节点创建一个专门的复制流,用于传输数据。 - 全量同步:
- 主节点处理:主节点在接收到从节点的同步请求后,会执行
BGSAVE
命令,生成当前数据库状态的RDB快照文件,并将此后接收到的写命令缓存起来。 - 从节点处理:从节点接收到主节点发送的RDB文件后,会先清空自己的数据库,然后加载RDB文件,将主节点的数据同步到本地。
- 数据同步完成:主节点将RDB文件发送完毕后,会将缓存的写命令依次发送给从节点,从节点执行这些命令,完成数据的最终同步。
- 主节点处理:主节点在接收到从节点的同步请求后,会执行
- 增量同步:全量同步完成后,主从节点进入增量同步阶段。主节点会将接收到的写命令通过复制流发送给从节点,从节点接收并执行这些命令,保持数据的一致性。
数据同步过程
- 初次同步:从节点启动并连接主节点,发送
PSYNC
命令(Redis 2.8及以上版本使用,早期版本使用SYNC
命令)。主节点根据从节点发送的runid
和offset
判断是否可以进行增量同步,如果是初次同步或无法进行增量同步,则进行全量同步。 - 增量同步:在主从节点正常运行过程中,主节点会持续记录自己的写操作到复制积压缓冲区(一个固定大小的环形缓冲区)。从节点会定期向主节点发送
REPLCONF ACK <offset>
命令,报告自己当前复制的偏移量。当从节点因为网络等原因与主节点断开连接后重新连接时,主节点根据从节点报告的偏移量判断是否可以进行增量同步。如果偏移量在复制积压缓冲区的范围内,则主节点将从偏移量开始的写命令发送给从节点,进行增量同步;否则,进行全量同步。
可能出现的数据不一致问题及解决方案
- 网络延迟导致的数据不一致:主节点在接收到写命令后,立即返回给客户端成功,而此时从节点可能还未同步到该数据。如果在这个时间窗口内客户端从从节点读取数据,就可能读到旧数据。
- 解决方案:
- 设置读偏好:应用程序可以根据业务需求,设置从节点的读偏好。例如,对于一些对数据一致性要求不高的读操作,可以从从节点读取数据;对于对数据一致性要求较高的读操作,从主节点读取数据。
- 使用同步读:在读取数据时,可以先等待一段时间,确保从节点已经同步到最新数据。可以通过
WAIT
命令(Redis 2.6及以上版本支持)实现,该命令可以阻塞客户端,直到指定数量的从节点确认接收到写命令。
- 解决方案:
- 复制积压缓冲区溢出导致的数据不一致:如果主节点产生写命令的速度过快,复制积压缓冲区可能会溢出,导致从节点重新连接时无法进行增量同步,只能进行全量同步,可能会出现数据不一致。
- 解决方案:合理设置复制积压缓冲区的大小。可以通过
repl-backlog-size
配置参数设置,一般根据主节点写命令的产生速度和网络状况来估算合适的大小。例如,如果主节点每秒产生100KB的写命令,网络中断时间可能长达10秒,那么可以将复制积压缓冲区大小设置为1MB(100KB * 10)以上。
- 解决方案:合理设置复制积压缓冲区的大小。可以通过
- 从节点故障恢复后的数据不一致:从节点在故障恢复后,可能会因为各种原因(如数据加载错误等)与主节点的数据不一致。
- 解决方案:定期对主从节点的数据进行一致性检查。可以使用Redis自带的
redis-check-aof
和redis-check-rdb
工具对AOF和RDB文件进行检查,也可以通过自定义脚本对比主从节点的数据。发现不一致时,及时采取措施,如重新进行全量同步等。
- 解决方案:定期对主从节点的数据进行一致性检查。可以使用Redis自带的