【源码阅读】5. 元数据

 

通常操作元数据时,会首先更新一条内存数据,然后写入一条元数据更新日志。

这样在重启时,通过顺序回放元数据更新日志,即可在内存中重构完整的元数据。

Doris一般使用BDBJE存放元数据的更新日志。在记录到达一定数量会在BDBJE中生成新的DB(本质是checkpoint分割点)

...

...

DB2

Log 19999

...

Log 10001

Log 10000

DB1

Log 9999

...

Log 2

Log 1

 

初始化

FE在使用BDBJE做元数据更新日志时,首先会在FE启动阶段初始化BEBJE的相关事宜:

● 构建ReplicatedEnvironment环境(BDBJE本身)

● 在BDBJE中查找数据库,并打开最后的那个数据库以供写入

● 设置写入的nextJournalId,以便下次写入时能得到正确的序列号

 

单机版BDBJE

元数据写入

EditLog.logEdit是元数据写入的方法,在其中

● 使用BDBJEJournal.write写入日志

● 自增txId

● 如果txId达到阈值则rollEditLog,在BDBJE中新建一个DB

 

 

EditLog.logEdit

    private synchronized void logEdit(short op, Writable writable) {
        journal.write(op, writable);

        // get a new transactionId
        txId++;

        if (txId >= Config.edit_log_roll_num) {
            LOG.info("txId {} is equal to or larger than edit_log_roll_num {}, will roll edit.", txId,
                    Config.edit_log_roll_num);
            rollEditLog();
            txId = 0;
        }
    }
 

BDBJEJournal.write

    public synchronized void write(short op, Writable writable) throws IOException {
        JournalEntity entity = new JournalEntity();
        entity.setOpCode(op);
        entity.setData(writable);

        // id is the key
        long id = nextJournalId.getAndIncrement();
        Long idLong = id;
        DatabaseEntry theKey = new DatabaseEntry();
        TupleBinding<Long> idBinding = TupleBinding.getPrimitiveBinding(Long.class);
        idBinding.objectToEntry(idLong, theKey);

        // entity is the value
        DataOutputBuffer buffer = new DataOutputBuffer(OUTPUT_BUFFER_INIT_SIZE);
        entity.write(buffer);

        DatabaseEntry theData = new DatabaseEntry(buffer.getData());
        if (currentJournalDB.put(null, theKey, theData) == OperationStatus.SUCCESS) {
            ...
        }
    }
 

Replay

以上实现了Doris元数据的持久化,FE节点宕机以后元数据不会丢失。遗留的问题还有:

● 日志越多,回放越慢

● 单节点故障如何保障高可用

 

Checkpoint

背景

如何保障FE的启动速度是通过checkpoint机制。定期将BDBJE中的日志合并成一个image,在启动时先加载image文件,从image后面那一条日志开始回放新的日志。

 

如何做

当BDBJE中新生成一个DB时,它会承接新的日志记录任务,前一个DB中的内容不会再发生变更,此时我们checkpoint到前一个DB结束即可,checkpoint文件的名字就是它记录的日志的位置。

Master FE会有一个定期任务,定期比较最新的checkpoint文件名与BDBJE前一个DB的最后一个日志位置,如果发现BDBJE前一个DB的最后一个日志位置更大,则说明可以做checkpoint。

● 先加载最新的checkpoint文件

● 回放到前DB的最后

● 将内存中的文件保存为checkpoint

● 其他FE拉取image

● 删除过期Database

● 删除过期image

和镜像相关的类为MetaPersistMethod

 

 

 

 

 

 
posted @ 2023-06-25 18:58  xutao_ustc  阅读(37)  评论(0编辑  收藏  举报