Redis源码解析--Replication

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介:         Redis的复制功能是基于内存快照即rdb的,也就是说无论使用哪种持久化机制,只要用到了复制功能,master都会产生内存快照即rdb,slave接收rdb以同步数据。Redis完成复制的源码主要分布在Replication.c(共610行中,分用于master和slave的函数,下面会详述过程。
         Redis的复制功能是基于内存快照即rdb的,也就是说 无论使用哪种持久化机制,只要用到了复制功能,master 都会产生内存快照即rdb,slave接收rdb以同步数据 Redis完成复制的源码主要分布在Replication.c(共610行中,分用于master和slave的函数,下面会详述过程。
一、状态
        Redis复制时slave和master都分别是一个状态机,状态定义在 Redis.h(162~179)中,主要状态如下:
/* Slave replication state - slave side */
#define REDIS_REPL_NONE 0 /* No active replication */
#define REDIS_REPL_CONNECT 1 /* Must connect to master */
#define REDIS_REPL_CONNECTING 2 /* Connecting to master */
#define REDIS_REPL_TRANSFER 3 /* Receiving .rdb from master */
#define REDIS_REPL_CONNECTED 4 /* Connected to master */


/* Synchronous read timeout - slave side */
#define REDIS_REPL_SYNCIO_TIMEOUT 5


/* Slave replication state - from the point of view of master
 * Note that in SEND_BULK and ONLINE state the slave receives new updates
 * in its output queue. In the WAIT_BGSAVE state instead the server is waiting
 * to start the next background saving in order to send updates to it. */
#define REDIS_REPL_WAIT_BGSAVE_START 3 /* master waits bgsave to start feeding it */
#define REDIS_REPL_WAIT_BGSAVE_END 4 /* master waits bgsave to start bulk DB transmission */
#define REDIS_REPL_SEND_BULK 5 /* master is sending the bulk DB */
#define REDIS_REPL_ONLINE 6 /* bulk DB already transmitted, receive updates */
        slave和master状态转换如下图:
图1 slave状 态机


图2 master状态机

        
二、 流程

图3 复制时序图
         从上图可以看出整个状态(红色部分为状态)转换流程如下:
         (1)初始情况下slave和master都处于REDIS_REPL_NONE Redis.c/initServerConfig()/1081 状态
         (2)slave从配置文件中读取或者从客户端接收到 slave of指令,slave 状态转换为REDIS_REPL_CONNECT(Replication.c/slaveofCommand/538 )。
         (3)slave在 定时任务serverCron( Redis.c/906 中调用replicationCron(Replicaltion.c/547)以连接master(Replication.c/connectWith),连接成功后slave状态转换为REDIS_REPL_CONNECTING(Replication.c/connectWithMaster/486
        (4)slave发送sync命令给master(Replication.c/syncWithMaster/426),slave状态转换为REDIS_REPL_TRANSFER(Replication.c/syncWithMaster/426)。
        (5)slave打开临时rdb文件用于存储即将要发送过来的快照数据(Replication.c/syncWithMaster/436),注册事件readSyncBulkPayLoad(Replication.c/syncWithMaster/446)用于接收快照数据,然后等待master发送回内存快照文件。

         (6)master收到sync命令后会跳转到syncCommand(Replication.c/83)函数,master状态转换为REDIS_REPL_BGSAVE_START(Replication.c/syncCommand/128),syncCommand函数判断是否有正在进行内存快照的子进程,如果有则等待其结束,没有则调用rdbSaveBackground(Rdb.c/685)函数立即开始内存快照,当快照完成后将master状态转换为REDIS_REPL_WAIT_BGSAVE_END(Replication.c/syncCommand/139)。
        (7)master主线程的定时任务serverCronRedis.c/906会检测做快照的子进程是否退出(Redis.c/serverCron/853),如果退出了则调用backgroundSaveDoneHandler(Redis.c/serverCron/854)函数,backgroundSaveDoneHandler会处理一些快照后的收尾工作,然后调用updateSlavesWaitingBgsave(Replication.c/208)函数。
        (8)master在函数updateSlavesWaitingBgsave中打开前面快照生成的rdb文件(Replication.c/updateSlavesWaitingBgsave/228),将master状态转换为REDIS_REPL_SEND_BULK(Replication.c/updateSlavesWaitingBgsave/236),并注册事件sendBulkToSave(Replication.c/updateSlavesWaitingBgsave/238)用于读取并发送上面打开的rdb快照数据给slave(Replication.c/148),发送完毕后将master状态转换为REDIS_REPL_ONLINE(Replication.c/sendBulkToSlave/191)。

         (9)slave通过步骤5中注册的事件readSyncBulkPayload来接收master发送的rdb数据(Replication.c/275),保存到本地,待接收完成后,调用emptydb(Db.c/140)以清空整个数据库,调用rdbLoad(Rdb.c/1015)重新读取master发送过来的内存快照文件以重建内存数据结构,并将状态置为REDIS_REPL_CONNECTED(Replication.c/readSyncBulkPayload/355),slave状态机转换完成,等待增量数据。
         (10)master在发送快照文件的过程中,接收的任何会改变数据集的命令都会暂时先保存在slave网络连接的发送缓存队列里(list数据结构 ),待快照完成后,依次发给slave。slave和master之间有心跳检测和超时退出。

、缺陷
        Redis的复制机制不支持增量复制,在slave连接master时,master需要进行内存快照,然后将整个快照数据发给slave,这会给master带来很大压力,slave接收完快照数据后会先清空数据库,再重建整个数据结构,这会导致数据大时slave同步时间非常长,所以需要注意slave和master之间的网络要非常稳定,不会闪断,否则这个过程会非常悲剧,因此,slave和master之间跨IDC机房或者南北电信都会有很大风险。另外,最好一开始就规划好slave的数量,否则,结果你懂的。。。

    
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
15天前
|
存储 缓存 NoSQL
深入解析Redis:一种快速、高效的键值存储系统
**Redis** 是一款高性能的键值存储系统,以其内存数据、高效数据结构、持久化机制和丰富的功能在现代应用中占有一席之地。支持字符串、哈希、列表、集合和有序集合等多种数据结构,适用于缓存、计数、分布式锁和消息队列等场景。安装Redis涉及下载、编译和配置`redis.conf`。基本操作包括键值对的设置与获取,以及哈希、列表、集合和有序集合的操作。高级特性涵盖发布/订阅、事务处理和Lua脚本。优化策略包括选择合适数据结构、配置缓存和使用Pipeline。注意安全、监控和备份策略,以确保系统稳定和数据安全。
62 1
|
1天前
|
存储 NoSQL Java
Redis 实现延迟任务的深度解析
【4月更文挑战第17天】
15 0
|
7天前
yolo-world 源码解析(六)(2)
yolo-world 源码解析(六)
16 0
|
7天前
yolo-world 源码解析(六)(1)
yolo-world 源码解析(六)
10 0
|
7天前
yolo-world 源码解析(五)(4)
yolo-world 源码解析(五)
17 0
|
7天前
yolo-world 源码解析(五)(1)
yolo-world 源码解析(五)
31 0
|
7天前
yolo-world 源码解析(二)(2)
yolo-world 源码解析(二)
20 0
|
7天前
Marker 源码解析(二)(3)
Marker 源码解析(二)
13 0
|
7天前
Marker 源码解析(一)(4)
Marker 源码解析(一)
11 0

推荐镜像

更多