#摘要: 在实际生产环境中,如何对 Doris 的元数据进行管理。包括 FE 节点建议的部署方式、一些常用的操作方法、以及常见错误的解决方法。
重要提示 当前元数据的设计是无法向后兼容的。即如果新版本有新增的元数据结构变动(可以查看 FE 代码中的 FeMetaVersion.java 文件中是否有新增的 VERSION),那么在升级到新版本后,通常是无法再回滚到旧版本的。所以,在升级 FE 之前,请务必按照 升级文档 中的操作,测试元数据兼容性。
在 fe.conf 中指定的 meta_dir 的路径为 /path/to/doris-meta。那么一个正常运行中的 Doris 集群,元数据的目录结构应该如下:
/path/to/doris-meta/
|-- bdb/
| |-- 00000000.jdb
| |-- je.config.csv
| |-- je.info.0
| |-- je.info.0.lck
| |-- je.lck
| `-- je.stat.csv
`-- image/
|-- ROLE
|-- VERSION
`-- image.xxxx
其中 .jdb 后缀的是 bdbje 的数据文件。这些数据文件会随着元数据 journal 的不断增多而越来越多。当 Doris 定期做完 image 后,旧的日志就会被删除。所以正常情况下,这些数据文件的总大小从几 MB 到几 GB 不等(取决于使用 Doris 的方式,如导入频率等)。当数据文件的总大小大于 10GB,则可能需要怀疑是否是因为 image 没有成功,或者分发 image 失败导致的历史 journal 一直无法删除。
je.info.0 是 bdbje 的运行日志。这个日志中的时间是 UTC+0 时区的。我们可能在后面的某个版本中修复这个问题。通过这个日志,也可以查看一些 bdbje 的运行情况。
你也可能会看到一个 image.ckpt 文件。这是一个正在生成的元数据镜像。通过 du -sh 命令应该可以看到这个文件大小在不断变大,说明镜像内容正在写入这个文件。当镜像写完后,会自动重名为一个新的 image.xxxxx 并替换旧的 image 文件。
只有角色为 Master 的 FE 才会主动定期生成 image 文件。每次生成完后,都会推送给其他非 Master 角色的 FE。当确认其他所有 FE 都收到这个 image 后,Master FE 会删除 bdbje 中旧的元数据 journal。所以,如果 image 生成失败,或者 image 推送给其他 FE 失败时,都会导致 bdbje 中的数据不断累积。
单节点 FE 是最基本的一种部署方式。一个完整的 Doris 集群,至少需要一个 FE 节点。当只有一个 FE 节点时,这个节点的类型为 Follower,角色为 Master。
假设在 fe.conf 中指定的 meta_dir 的路径为 /path/to/doris-meta。
确保 /path/to/doris-meta 已存在,权限正确,且目录为空。
直接通过 sh bin/start_fe.sh 即可启动。
启动后,你应该可以在 fe.log 中看到如下日志:
Palo FE starting...
image does not exist: /path/to/doris-meta/image/image.0
transfer from INIT to UNKNOWN
transfer from UNKNOWN to MASTER
the very first time to open bdb, dbname is 1
start fencing, epoch number is 1
finish replay in xxx msec
QE service start
thrift server started
以上日志不一定严格按照这个顺序,但基本类似。
单节点 FE 的第一次启动通常不会遇到问题。如果你没有看到以上日志,一般来说是没有仔细按照文档步骤操作,请仔细阅读相关 wiki。
直接使用 sh bin/start_fe.sh 可以重新启动已经停止的 FE 节点。
重启后,你应该可以在 fe.log 中看到如下日志:
Palo FE starting...
finished to get cluster id: xxxx, role: FOLLOWER and node name: xxxx
如果重启前还没有 image 产生,则会看到:
image does not exist: /path/to/doris-meta/image/image.0
如果重启前有 image 产生,则会看到:
start load image from /path/to/doris-meta/image/image.xxx. is ckpt: false
finished load image in xxx ms
transfer from INIT to UNKNOWN
replayed journal id is xxxx, replay to journal id is yyyy
transfer from UNKNOWN to MASTER
finish replay in xxx msec
master finish replay journal, can write now.
begin to generate new image: image.xxxx
start save image to /path/to/doris-meta/image/image.ckpt. is ckpt: true
finished save image /path/to/doris-meta/image/image.ckpt in xxx ms. checksum is xxxx
push image.xxx to other nodes. totally xx nodes, push successed xx nodes
QE service start
thrift server started
以上日志不一定严格按照这个顺序,但基本类似。
添加 FE 流程在 弹性扩缩容 有详细介绍,不再赘述。这里主要说明一些注意事项,以及常见问题。
如果添加的是 FOLLOWER,因为 FOLLOWER 是参与元数据多数写的。所以有可能FOLLOWER 已经加入 bdbje 选举组内。如果这时只有两个 FOLLOWER 节点(包括 MASTER),那么停掉一个 FE,可能导致另一个 FE 也因无法进行多数写而退出。此时,我们应该先通过 ALTER SYSTEM DROP FOLLOWER 命令,从元数据中删除新添加的 FOLLOWER 节点,然后再杀死 FOLLOWER 进程,清空元数据,重新进行一遍添加流程。
通过 ALTER SYSTEM DROP FOLLOWER/OBSERVER 命令即可删除对应类型的 FE。以下有几点注意事项:
如果删除非 MASTER 角色的 FE,建议连接到 MASTER FE,执行 DROP 命令,再杀死进程即可。 如果要删除 MASTER FE,先确认有奇数个 FOLLOWER FE 并且运行正常。然后先杀死 MASTER FE 的进程。这时会有某一个 FE 被选举为 MASTER。在确认剩下的 FE 运行正常后,连接到新的 MASTER FE,执行 DROP 命令删除之前老的 MASTER FE 即可。
FE 有可能因为某些原因出现无法启动 bdbje、FE 之间无法同步等问题。现象包括无法进行元数据写操作、没有 MASTER 等等。这时,我们需要手动操作来恢复 FE。手动恢复 FE 的大致原理,是先通过当前 meta_dir 中的元数据,启动一个新的 MASTER,然后再逐台添加其他 FE。请严格按照如下步骤操作:
如果你是从一个 OBSERVER 节点的元数据进行恢复的,那么完成如上步骤后,通过
show frontends;
语句你会发现,当前这个 FE 的角色为 OBSERVER,但是IsMaster
显示为true
。这是因为,这里看到的 “OBSERVER” 是记录在 Doris 的元数据中的,而是否是 master,是记录在 bdbje 的元数据中的。因为我们是从一个 OBSERVER 节点恢复的,所以这里出现了不一致。请按如下步骤修复这个问题(这个问题我们会在之后的某个版本修复):
ADD FOLLOWER
命令,添加一个新的 FOLLOWER FE,假设在 hostA 上。--helper
的方式加入集群。show frontends;
语句,你应该能看到两个 FE,一个是之前的 OBSERVER,一个是新添加的 FOLLOWER,并且 OBSERVER 是 master。
metadata_failure_recovery=true
的含义是,清空 “bdbje” 的元数据。这样 bdbje 就不会再联系之前的其他 FE 了,而作为一个独立的 FE 启动。这个参数只有在恢复启动时才需要设置为 true。恢复完成后,一定要设置为 false,否则一旦重启,bdbje 的元数据又会被清空,导致其他 FE 无法正常工作。
如果你需要将当前已有的 FOLLOWER/OBSERVER 类型的 FE,变更为 OBSERVER/FOLLOWER 类型,请先按照前面所述的方式删除 FE,再添加对应类型的 FE 即可
如果你需要将一个 FE 从当前节点迁移到另一个节点,分以下几种情况。
FE 目前有以下几个端口
在某些极端情况下,磁盘上 image 文件可能会损坏,但是内存中的元数据是完好的,此时我们可以先从内存中 dump 出元数据,再替换掉磁盘上的 image 文件,来恢复元数据,整个不停查询服务的操作步骤如下:
集群停止所有 Load,Create,Alter 操作
执行以下命令,从 Master FE 内存中 dump 出元数据:(下面称为 image_mem)
curl -u $root_user:$password http://$master_hostname:8030/dump
用 image_mem 文件替换掉 OBSERVER FE 节点上meta_dir/image目录下的 image 文件,重启 OBSERVER FE 节点, 验证 image_mem 文件的完整性和正确性(可以在 FE Web 页面查看 DB 和 Table 的元数据是否正常,查看fe.log 是否有异常,是否在正常 replayed journal)
自 1.2.0 版本起,推荐使用以下功能验证 image_mem
文件:
sh start_fe.sh --image path_to_image_mem
注意:
path_to_image_mem
是 image_mem 文件的路径。 如果文件有效会输出Load image success. Image file /absolute/path/to/image.xxxxxx is valid
。 如果文件无效会输出Load image failed. Image file /absolute/path/to/image.xxxxxx is invalid
。
注意:如果 Image 文件很大,整个操作过程耗时可能会很长,所以在此期间,要确保 Master FE 不会通过 checkpoint 生成新的 image 文件。当观察到 Master FE 节点上 meta_dir/image目录下的 image.ckpt 文件快和 image.xxx 文件一样大时,可以直接删除掉image.ckpt 文件。
FE 的元数据日志以 Key-Value 的方式存储在 BDBJE 中。某些异常情况下,可能因为元数据错误而无法启动 FE。在这种情况下,Doris 提供一种方式可以帮助用户查询 BDBJE 中存储的数据,以方便进行问题排查。
首先需在 fe.conf 中增加配置:enable_bdbje_debug_mode=true,之后通过 sh start_fe.sh –daemon 启动 FE。
此时,FE 将进入 debug 模式,仅会启动 http server 和 MySQL server,并打开 BDBJE 实例,但不会进行任何元数据的加载及后续其他启动流程。
这是,我们可以通过访问 FE 的 web 页面,或通过 MySQL 客户端连接到 Doris 后,通过 show proc /bdbje; 来查看 BDBJE 中存储的数据。
mysql> show proc "/bdbje";
+----------+---------------+---------+
| DbNames | JournalNumber | Comment |
+----------+---------------+---------+
| 110589 | 4273 | |
| epochDB | 4 | |
| metricDB | 430694 | |
+----------+---------------+---------+
第一级目录会展示 BDBJE 中所有的 database 名称,以及每个 database 中的 entry 数量。
mysql> show proc "/bdbje/110589";
+-----------+
| JournalId |
+-----------+
| 1 |
| 2 |
...
| 114858 |
| 114859 |
| 114860 |
| 114861 |
+-----------+
4273 rows in set (0.06 sec)
进入第二级,则会罗列指定 database 下的所有 entry 的 key。
mysql> show proc "/bdbje/110589/114861";
+-----------+--------------+---------------------------------------------+
| JournalId | OpType | Data |
+-----------+--------------+---------------------------------------------+
| 114861 | OP_HEARTBEAT | org.apache.doris.persist.HbPackage@6583d5fb |
+-----------+--------------+---------------------------------------------+
1 row in set (0.05 sec)
第三级则可以展示指定 key 的 value 信息。
FE 的部署推荐,在 安装与部署文档 中有介绍,这里再做一些补充。
这个通常是因为 FE 无法选举出 Master。比如配置了 3 个 FOLLOWER,但是只启动了一个 FOLLOWER,则这个 FOLLOWER 会出现这个问题。通常,只要把剩余的 FOLLOWER 启动起来就可以了。如果启动起来后,仍然没有解决问题,那么可能需要按照 故障恢复 一节中的方式,手动进行恢复。
同时,你也可以在 FE 的配置文件中添加配置:edit_log_roll_num=xxxx。该参数设定了每多少条元数据 journal,做一次 image。默认是 50000。可以适当改小这个数字,使得 image 更加频繁,从而加速删除旧的 journal。
如果在单 Follower FE 部署中,master_sync_policy 设置为 WRITE_NO_SYNC,则可能出现 FE 系统宕机导致元数据丢失。这时如果有其他 Observer FE 尝试重启时,可能会报错:
Node xxx must rollback xx total commits(numPassedDurableCommits of which were durable) to the earliest point indicated by transaction xxxx in order to rejoin the replication group, but the transaction rollback limit of xxx prohibits this.
意思有部分已经持久化的事务需要回滚,但条数超过上限。这里我们的默认上限是 100,可以通过设置 txn_rollback_limit 改变。该操作仅用于尝试正常启动 FE,但已丢失的元数据无法恢复。