在 Doris 数据库的运行过程中,Compaction 作为一项关键机制,对数据的存储和查询性能有着巨大影响。然而,如同任何复杂的系统,Compaction 过程也可能遭遇各类问题,影响数据库的正常运行和性能表现。本文将详细探讨一些常见的 Compaction 问题,包括 Compaction score 高、Compaction 失败、Compaction 占用资源多以及 Compaction 导致 BE core 等情况,并提供相应的排查思路和处理手段。
Compaction 持续失败,score 就容易升高。那该如何定位是compaction失败了呢?
“curl ip:port/api/compaction/show?tablet_id=${tablet_id}” 查 compaction 状态。
bucket 数量没设置好
bucket 数量设得太小,compaction 无法充分并发;设得太大,任务调度又过多。一般建议按 tablet 1GB - 10GB 的最佳实践来设置。
delete 操作太频繁:
查看 compaction status,若有大量 delete,就可能是这问题。比如电商交易数据分析场景,用户频繁删无效订单,compaction 处理大量 delete 标记,score 升高,性能下降。
当 compaction 消费者线程满负荷,score 还高,就得找找原因了。
判断方法:使用下面的方式来查看compaction 一段时间内的平均并发数
cat be/log/be.INFO | grep -E "succeed to do base compaction|succeed to do cumulative compaction" | awk '{print $23}' | awk -F= '{print $2}' | awk -Fs '{sum+=$1} END {print sum}'
细分原因:
线程数不够:
常见问题是用户在 be conf 里只配了 1 块盘,导致只有一个 cumu thread。因此只有一个cumu thread。
处理方式:调大线程数,下列为对应的配置名,支持动态修改。max_base_compaction_threads ,max_cumu_compaction_threads
★注意:调整的时候,注意观察用户磁盘的cpu,io util等资源
稀疏宽表拖慢节奏:表列多但单行数据不大,比如上千列,一行几百字节,通过 “show tablets from table” 或 compaction 日志估算单行长度(input_rowset_size /input_row_num)
若符合这种情况,调整 BE 配置 “vertical_compaction_num_columns_per_group = 50” 即可。
线程池没用满,score 却高,可能是调度问题。
total permits 限制:permits 限制 compaction 多路归并排序多路数来控制内存,但队列中的 task 也占 permits,导致任务多时有并发限制。
判断方法是:
处理方式是调大 BE 参数 “total_permits_for_compaction_score = 1000000” 。
tablet 太多调度慢:Compaction 生产者扫描磁盘生成 task,tablet 太多,扫描耗时久,任务生产就慢。
判断方法是:
tablet skip 机制出问题:频繁的元信息扫描会导致大量的 CPU 资源浪费。因此在 Doris 2.0.0 版本中引入了 Tablet 休眠机制,来降低元数据扫描带来的 CPU 开销。通过对长时间没有 Compaction 任务的 Tablet 设置休眠时间,一段时间内不再对该 Tablet 进行扫描,能够大幅降低任务扫描的压力。同时如果休眠的 Tablet 有突发的导入,通过主动触发的方式也能顾唤醒 Compaction 任务,不会对任务的实时性有任何影响。
通过上述的主动扫描+被动触发+休眠机制,使用最小的资源消耗,保证了 Compaction 任务触发的实时性。2.1 版本修改主动扫描机制后,此休眠机制在高频导入场景有问题。
判断方法是:
处理方式是设 BE 配置 “enable_skip_tablet_compaction = false”(不支持动态修改)。
内存超限不触发:内存使用超过软限,导致没有触发compaction
判断方法是:
处理办法是降低 BE 内存使用。
单盘并发受限:Compaction 生产者线程判断磁盘并发 compaction 是否超限制,超了就不再产生该盘 task。
判断方法是:
对于 Compaction score 高的问题,可调整 “max_tablet_version_num”(默认 2000),还能手动触发 compaction,临时处理用 “curl -X POST http://be_host:webserver_port/api/compaction/run?tablet_id=xxxx&compact_type=cumulative”。同时,要收集 Compaction score 监控、BE 日志、tablet 的 rowset 布局(“curl be_ip:webserver_port/api/compaction/show?tablet_id=${tablet_id}” 获取)等信息。
通过 “grep compaction be.INFO | grep {tablet_id}” 看失败原因,内存分配失败日志类似。
W0427 19:40:58.254163 7873 compaction.cpp:372] fail to do CloudBaseCompaction. res=[MEM_LIMIT_EXCEEDED] PreCatch error code:11, [E11] Allocator sys memory check failed: Cannot alloc:5148, consuming tracker:[BaseCompaction:135202205](BaseCompaction:135202205), peak used 1435738416, current used 1164740816, exec node:<>, process memory used 105.03 GB exceed limit 109.63 GB or sys available memory 11.71 GB less than low water mark 12.18 GB. no enable stack, _FILE:/home/ec2-user/selectdb-core/be/src/olap/rowset/segment_v2/segment_iterator.cpp, __LINE:2000, _*FUNCTION*:auto doris::segment_v2::SegmentIterator::next_batch (vectorized::Block *)::(anonymous class)::operator ()() const, tablet=135202205.758764227.6e8b36c0cc1b4ac2-9f14bb5b6d058fe6, output_version=[2-8237]
细分有以下几种情况:
对于上述细分的原因需要查看memtracker,当前compaction内存使用的情况来定位。
通过日志判断,
W0319 16:13:58.449980 1221594 cumulative_compaction.cpp:113] There are missed versions among rowsets. prev rowset verison=[2-209], next rowset version=[218-218], tablet=143405174.1524602546.e44ef3f8419888cf-c1c834105ff8d0b3
解决办法是处理 missing rowset 问题。 解决办法参考文档:Doris Tablet 损坏如何应对?能恢复数据吗?
用 “top -H” 确认是否是 compaction 线程导致。
处理方法有两种:一是调做 compaction 的线程数量,“max_base_compaction_threads”(默认 4 )和 “max_cumu_compaction_threads”(默认每块盘 1 个);二是调每个盘上 compaction 的并发数量,HDD 盘调 “compaction_task_num_per_disk”(默认 4),SSD 盘调 “compaction_task_num_per_fast_disk”(默认 8)。调节后要盯着 compaction score 变化,防止并发限制过小导致 score 升高。
参考 Compaction 失败中内存超限导致失败的处理方式。
收集 be.out、BE.info、core dump、be 版本信息(含具体 commit id),备注特殊操作,比如 scheam change 等。然后提供信息找一下社区同学,辅助解决。
这种情况可能影响使用,先止损。用 “show tablet {tablet_id}” 通过 tablet id 找到表,然后配置 BE.conf“disable_auto_compaction = true” 关闭 BE 的 compaction,再用 “alter table ${tableName} set ("disable_auto_compaction" = "true")” 关掉表的 compaction,最后再打开 BE 的 compaction(配置 BE.conf“disable_auto_compaction = false”)。虽然 core 出现在 compaction 栈上,但不一定是 compaction 的问题,因为它是后台持续读写线程,查询也可能出现 core,只是没被发现。
今天关于 Doris 中 Compaction 问题的解析就到这里啦!大家在实际使用中遇到相关问题,不妨按照文中方法试试。要是还有疑问,欢迎在评论区留言,我们一起探讨。或者直接联系社区同学 OR me,也别忘了点赞、分享给更多有需要的小伙伴!