StarRocks源码阅读系列(4)2.5版本新compaction机制

本文通过对StarRocks2.5.3版本源码的阅读,详细解析了compaction机制,特别是新引入的分层压缩(SizeTieredCompaction)策略。该策略将tablet分为多个层次,根据数据大小和版本分布进行压缩,优化了压缩效率。文章还介绍了compaction任务的调度、候选队列管理和触发条件等关键环节。
摘要由CSDN通过智能技术生成

StarRocks源码阅读:2.5版本compaction机制

前言

最近由于业务需要搭建了StarRocks2.5.3版本的集群,但是在使用过程中发现曾经在2.3版本设置的一些配置项在2.5版本不太好用,看起来需要重新盘一盘2.5版本的compaction压缩机制了。
本文是通过StarRocks2.5.3版本源码进行阅读梳理的,其他版本内容仅供参考。

源码阅读

_schedule


void CompactionManager::_schedule() {
   
    LOG(INFO) << "start compaction scheduler";
    while (!_stop.load(std::memory_order_consume)) {
   
        ++_round;
        _wait_to_run();
        std::shared_ptr<CompactionTask> compaction_task = _try_get_next_compaction_task();
        if (!compaction_task) {
   
            std::unique_lock<std::mutex> lk(_mutex);
            _cv.wait_for(lk, 1000ms);
        } else {
   
            if (compaction_task->compaction_type() == CompactionType::BASE_COMPACTION) {
   
                StarRocksMetrics::instance()->tablet_base_max_compaction_score.set_value(
                        compaction_task->compaction_score());
            } else {
   
                StarRocksMetrics::instance()->tablet_cumulative_max_compaction_score.set_value(
                        compaction_task->compaction_score());
            }

            compaction_task->set_task_id(next_compaction_task_id());
            LOG(INFO) << "submit task to compaction pool"
                      << ", task_id:" << compaction_task->task_id()
                      << ", tablet_id:" << compaction_task->tablet()->tablet_id()
                      << ", compaction_type:" << starrocks::to_string(compaction_task->compaction_type())
                      << ", compaction_score:" << compaction_task->compaction_score() << " for round:" << _round
                      << ", task_queue_size:" << candidates_size();
            auto st = _compaction_pool->submit_func([compaction_task] {
    compaction_task->start(); });
            if (!st.ok()) {
   
                LOG(WARNING) << "submit compaction task " << compaction_task->task_id()
                             << " to compaction pool failed. status:" << st.to_string();
                compaction_task->tablet()->reset_compaction();
                CompactionCandidate candidate;
                candidate.tablet = compaction_task->tablet();
                update_candidates({
   candidate});
            }
        }
    }
}

首先注意到的地方是compaction_manager.cpp的_schedule函数,根据字面意思,这个函数是所有压缩的调度器,用来向compaction pool提交待压缩任务的。

它是通过_try_get_next_compaction_task()函数获取的待压缩任务队列。

_try_get_next_compaction_task


std::shared_ptr<CompactionTask> CompactionManager::_try_get_next_compaction_task() {
   
    VLOG(2) << "try to get next qualified tablet for round:" << _round
            << ", current candidates size:" << candidates_size();
    CompactionCandidate compaction_candidate;
    std::shared_ptr<CompactionTask> compaction_task = nullptr;

    if (pick_candidate(&compaction_candidate)) {
   
        compaction_task = compaction_candidate.tablet->create_compaction_task();
    }

    return compaction_task;
}

这个函数比较短,可以看出由pick_candidate函数来选择的压缩候选者。

pick_candidate

bool CompactionManager::pick_candidate(CompactionCandidate* candidate) {
   
    std::lock_guard lg(_candidates_mutex);
    if (_compaction_candidates.empty()) {
   
        return false;
    }

    auto iter = _compaction_candidates.begin();
    while (iter != _compaction_candidates.end()) {
   
        if (_check_precondition(*iter)) {
   
            *candidate = *iter;
            _compaction_candidates.erase(iter);
            return true;
        }
        iter++;
    }

    return false;
}

接下来看pick_candidate函数,首先有一个_compaction_candidates队列,循环这个队列,对每一行调用一次_check_precondition函数进行判断,如果满足压缩前置条件,那么就出队并返回true。
这里有2个函数需要注意

  1. _compaction_candidates队列的设计,待压缩的tablet是怎样入队的。
  2. _check_precondition函数的判断逻辑。

update_candidates


void CompactionManager::update_candidates(std::vector<CompactionCandidate> candidates) {
   
    size_t erase_num = 0;
    {
   
        std::lock_guard lg(_candidates_mutex);
        // TODO(meegoo): This is very inefficient to implement, just to fix bug, it will refactor later
        for (auto iter = _compaction_candidates.begin(); iter != _compaction_candidates.end();) {
   
            bool has_erase = false;
            for (auto& candidate : candidates) {
   
                if (candidate.tablet->tablet_id() == iter->tablet->tablet_id()) {
   
                    iter = _compaction_candidates.erase(iter);
                    erase_num++;
                    has_erase = true;
                    break;
                }
            }
            if (!has_erase) {
   
                iter++;
            }
        }
        for (auto& candidate : candidates) {
   
            if (candidate.tablet->enable_compaction()) {
   
                VLOG(1) << "update candidate " << candidate.tablet->tablet_id() << " type "
                        << starrocks::to_string(candidate.type) << " score " << candidate.score;
                _compaction_candidates.emplace(std::move(candidate));
            }
        }
    }
    _notify();
}

这个函数是队列的入队函数,它主要是将candidates队列进行了1次循环,将所有开启了compaction的tablet进行了入队操作。
在这段代码中有一个TODO备注,根据描述未来这里会重构。
读到这里又有2个疑问需要继续阅读

  1. candidates 队列维护机制
  2. update_candidates 调用机制

update_tablet


                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lixiaoer666

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值