【源码阅读】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