config repl-stream-db

背景:

同步数据的时候,源节点是主库时,则增量的第一条数据是 select 命令。

当源节点使用的从库,发现同步完 RDB 之后,第一条增量的数据并没有 select db,故而会默认写到到 db0,其实增量的数据应该写到 db3 的,这个是否发现应该读取 rdb 中的 repl-stream-db 信息,使用此 db 作为第一条增量同步的命令。

在 Redis 的持久化与复制机制中,repl-stream-dbRDB 文件头部的元数据字段之一,用于记录持久化时主节点正在使用的数据库编号(即当前选中的 DB)。其核心作用是为复制过程提供上下文信息,确保从节点能正确加载数据并同步到对应数据库。以下是详细说明:

1 字段来源与存储位置

  • RDB 文件结构:Redis 的 RDB 持久化文件由文件头和实际数据组成。文件头包含元数据(如 Redis 版本、复制信息等),而 repl-stream-db 是文件头中的关键字段之一。

  • 存储内容:该字段记录主节点在生成 RDB 文件时使用的数据库编号(如 DB 0DB 1 等),从节点通过解析此字段可确定数据应加载到哪个数据库。

2 核心作用

  • 复制同步的上下文保障

    • 在主从复制中,主节点生成 RDB 文件后,会将文件传输给从节点。从节点需知道数据应加载到哪个数据库,而 repl-stream-db 提供了这一信息,避免从节点错误地将数据写入默认数据库(如 DB 0)。

    • 例如,若主节点在生成 RDB 时使用的是 DB 1,从节点会通过此字段将数据加载到 DB 1,确保主从数据一致性。

  • 支持增量复制的元数据

    • 当 Redis 配置了 appendonly yes(启用 AOF)且 AOF 文件包含 RDB 前导(即混合持久化模式)时,repl-stream-db 会出现在 AOF 文件的 RDB 前导部分,为后续的增量复制提供数据库上下文。

3 场景

DTS 同步数据场景,如 redis-shake 同步数据时,解析 RDB 时,返回下 repl-stream-db

(RedisShake-4)internal/rdb/rdb.go

// ParseRDB parse rdb file
// return repl stream db id
func (ld *Loader) ParseRDB(ctx context.Context) int {
	var err error
	ld.fp, err = os.OpenFile(ld.filPath, os.O_RDONLY, 0666)
	if err != nil {
		log.Panicf("open file failed. file_path=[%s], error=[%s]", ld.filPath, err)
	}
	defer func() {
		err = ld.fp.Close()
		if err != nil {
			log.Panicf("close file failed. file_path=[%s], error=[%s]", ld.filPath, err)
		}
	}()
	rd := bufio.NewReader(ld.fp)
	// magic + version
	buf := make([]byte, 9)
	_, err = io.ReadFull(rd, buf)
	if err != nil {
		log.Panicf(err.Error())
	}
	if !bytes.Equal(buf[:5], []byte("REDIS")) {
		log.Panicf("verify magic string, invalid file format. bytes=[%v]", buf[:5])
	}
	version, err := strconv.Atoi(string(buf[5:]))
	if err != nil {
		log.Panicf(err.Error())
	}
	log.Debugf("[%s] RDB version: %d", ld.name, version)

	// read entries
	ld.parseRDBEntry(ctx, rd)

	return ld.replStreamDbId
}

Last updated