基于AOF的Redis Migrate Tool

 

Redis Migrate Tool (RMT) 是唯品会(Vipshop)开发的一款高性能Redis数据迁移工具,支持多种Redis部署模式间的数据迁移,包括单实例、Twemproxy、Redis集群以及从RDB/AOF文件加载数据

RMT工具概述

RMT具有以下核心特性:

  • 高速多线程迁移
  • 基于Redis复制协议
  • 在线迁移(源Redis可持续服务)
  • 异构迁移(支持不同Redis部署模式间转换)
  • 支持Twemproxy和Redis集群
  • 迁移状态实时查看
  • 数据验证机制

AOF迁移配置示例

AOF迁移的典型配置如下:

[source]
type: aof file
servers:
 - /data/redis/appendonly1.aof
 - /data/redis/appendonly2.aof

[target]
type: redis cluster
servers:
 - 127.0.0.1:7379

[common]
listen: 0.0.0.0:8888
step: 2

此配置表示从多个AOF文件加载数据并迁移到Redis集群。

AOF迁移实现原理

RMT的AOF迁移实现涉及以下关键流程:

1. 初始化阶段

// rmt.c中加载配置并初始化上下文
int init_context(struct instance *nci) {
    // 加载配置文件
    nci->conf = conf_create(nci->conf_filename);
    
    // 初始化核心组件
    core_init();
}

// 触发迁移流程
void core_start() {
    // 调用迁移主函数
    redis_migrate();
}

2. 迁移启动阶段

// rmt_core.c中创建Redis组
static void redis_migrate() {
    // 创建源组
    source_group = source_group_create();
    
    // 确定读写线程数量(读线程占20%)
    read_threads = total_threads * 0.2;
    write_threads = total_threads - read_threads;
    
    // 根据配置创建Redis组对象
    group_create_from_option(option);
}

对于AOF文件源,RMT会:

  1. 将source_type设置为GROUP_TYPE_AOF_FILE
  2. 解析配置中的AOF文件路径
  3. 为每个AOF文件创建处理结构

3. AOF解析与数据迁移流程

AOF迁移的关键流程包括:

// 1. 读取AOF文件
int aof_reader_start() {
    // 打开AOF文件
    fd = open(aof_path, O_RDONLY);
    
    // 创建AOF解析器
    aof_parser = aof_parser_create();
    
    // 开始解析过程
    aof_parse_commands();
}

// 2. 解析AOF命令
int aof_parse_commands() {
    while ((cmd = aof_parser_next_command()) != NULL) {
        // 将AOF命令转换为内部命令结构
        rmt_command = convert_aof_to_command(cmd);
        
        // 将命令加入处理队列
        enqueue_command(rmt_command);
        
        // 通知写线程处理
        notify_write_thread();
    }
}

// 3. 写线程处理
void writeThreadCron() {
    // 监听通知管道
    if (pipe_readable()) {
        // 从队列获取命令
        cmd = dequeue_command();
        
        // 发送到目标Redis
        send_data_to_target(cmd);
        
        // 接收目标响应
        recv_data_from_target();
    }
}

4. 写线程同步机制

从提供的信息可以看出,RMT使用管道通信机制在读线程和写线程之间传递同步请求:

// 写线程主循环
void *writeThreadMain() {
    while (!stop) {
        // 等待管道中的通知
        event_wait(pipe_event);
        
        // 从链表获取要发送的数据
        data = list_pop_front(pending_data);
        
        // 发送数据到目标
        send_data_to_target(data);
        
        // 接收目标响应
        recv_data_from_target();
    }
}

数据流和内存管理

AOF迁移过程中的数据流如下:

  1. AOF文件读取 → 文件内容被读入内存
  2. AOF解析 → 解析AOF格式,提取有效Redis命令
  3. 命令队列 → 解析后的命令存储在内存队列中
  4. 写线程处理 → 从队列获取命令并发送到目标Redis
  5. 响应处理 → 接收目标Redis的响应并确认命令执行成功

为了高效处理大量数据,RMT在内存中使用链表结构暂存待处理的命令,并通过step参数控制批处理大小,平衡内存使用和性能。

与RDB迁移的区别

相比RDB迁移,AOF迁移具有以下特点:

  1. 命令级别迁移:AOF迁移是按命令重放,而RDB迁移是按对象复制
  2. 增量特性:AOF包含增量命令记录,可以捕获最新变更
  3. 处理逻辑不同
    • RDB: rmtRedisRdbDataPost() → 解析RDB文件结构 → 转换为对象
    • AOF: 直接解析命令文本 → rmtRedisSlaveReadQueryFromMaster → 发送命令