首页 > 其他分享 >RocksDB代码分析——写入流程

RocksDB代码分析——写入流程

时间:2024-09-28 13:39:30浏览次数:1  
标签:调用 写入 流程 RocksDB DB flush leader DBImpl MemTableInserter

分析均基于v6.27.3。以下流程为了方便理解均经过了简化。

首先,我们通过调用DB::Open来创建数据库,它返回了一个DB*DB::Open内部调用了DBImpl::Open,在里面构造了一个DBImpl*并转换成DB*返回。所以我们拿到的DB*其实是DBImpl*

然后我们调用DB::Put来写入数据。DB::Put是个virtual函数,它被DBImpl::Put给override了:

Status DBImpl::Put(const WriteOptions& o, ColumnFamilyHandle* column_family,
                   const Slice& key, const Slice& val) {
  return DB::Put(o, column_family, key, val);
}

它显式调用了DB::PutDB::Put中首先构造了WriteBatch,然后调用了DB::Write,它是个纯虚函数,被DBImpl::Write override了。DBImpl::Write调用了DBImpl::WriteImpl

DBImpl::WriteImpl先检查了一堆option,这里我们先不管。然后将WriteBatch *my_batch以及WriteOption都转移到了WriteThread::Writer w中。然后调用WriteThread::JoinBatchGroup

  • 假如我们不是leader

leader可能帮我们做了插入,这时直接返回即可。

如果leader告诉我们要自己插入到MemTable,那么调用WriteBatchInternal::InsertInto把数据插入到MemTable中,然后返回。

  • 假如我们是leader(每个时刻只有一个leader)

调用DBImpl::PreprocessWrite

如果flush_scheduler_中有任务,就调用DBImpl::ScheduleFlushes(唯一调用者)。

先调用FlushScheduler::TakeNextColumnFamily(正常状态下唯一调用者),它是唯一从FlushScheduler中取出flush任务(以ColumnFamilyData的形式)的方法。
逐个将这些取出的ColumnFamilyData cfd作为参数调用DBImpl::SwitchMemtable,将这些column family data的memory table变成immutable memory table,然后新建一个memory table。这里没有用原子操作,但是其他非leader的writer应该是没有拿DB mutex的。可能这是因为其他非leader的writer都在等leader给出指示。具体没细看。
将之前取出的ColumnFamilyData cfd作为DBImpl::GenerateFlushRequest的参数,得到FlushRequest flush_req,再将其作为DBImpl::SchedulePendingFlush的参数。
DBImpl::SchedulePendingFlush中,将给传进来的flush_req里的cfdcfd->Ref(),然后加入到DBImpl::flush_queue_里。
接下来的flush流程看这里:

写入WAL
调用WriteBatchInternal::InsertInto把数据插入到MemTable。

WriteBatchInternal::InsertInto中先构造了MemTableInserter inserter,然后执行writer->batch->Iterate(&inserter),即执行WriteBatch::Iterate(Handler* handler),其中handler其实是MemTableInserter*类型的。WriteBatch::Iterate中调用了WriteBatchInternal::Iterate

WriteBatchInternal::Iterate中将WriteBatch中的record逐个读出来,按照record上的tag执行相应的操作。我们这里只关注tag为kTypeValuekTypeColumnFamilyValue的record,对这种record,执行handler->PutCF(column_family, key, value),即调用WriteBatch::Handler::PutCF,将对应的key和value插入。WriteBatch::Handler::PutCF是个virtual函数,注意到这里的handler其实是MemTableInserter*类型的,所以这里调用的其实是MemTableInserter::PutCFMemTableInserter::PutCF中又调用了MemTableInserter::PutCFImpl

MemTableInserter::PutCFImpl先调用MemTable::Add将key和value插入到MemTable中,再调用MemTableInserter::CheckMemtableFull

MemTableInserter::CheckMemtableFull大意:

if (cfd->mem()->ShouldScheduleFlush())
    flush_scheduler_->ScheduleWork(cfd);

FlushScheduler::ScheduleWork中,先cfd->Ref(),然后把cfd放进链表里。前面提到了,在DBImpl::WriteImpl中作为leader时,会检查FlushScheduler flush_scheduler_中有没有任务,有的话就拿出来放到DBImpl::flush_queue_中。

我的问题:为什么不直接放到DBImpl::flush_queue_中?

标签:调用,写入,流程,RocksDB,DB,flush,leader,DBImpl,MemTableInserter
From: https://www.cnblogs.com/searchstar/p/18437455

相关文章

  • RocksDB代码分析——LogAndApply
    这里我们主要分析VersionSet::LogAndApply是怎么管理writer队列的。参数里的edit_lists是需要被apply的改动。每个传入的columnfamilydata对应edit_lists里的一个editlist,即autovector<VersionEdit*>。接下来把每个editlist打包成一个ManifestWriter,放进std::deque<Manifest......
  • RocksDB代码分析——Flush流程
    这里从DBImpl::MaybeScheduleFlushOrCompaction开始讲起。DBImpl::MaybeScheduleFlushOrCompaction可能会scheduleDBImpl::BGWorkFlush和DBImpl::BGWorkCompaction。这里主要看Flush。Compaction部分见:{%post_linkStorage/'RocksDB代码分析——Compaction流程'%}DBImpl::BGWo......
  • RocksDB代码分析——Compaction的输入文件的选择
    这里主要分析LevelCompactionBuilder::PickCompaction是如何选择输入文件的。SetupInitialFiles();找一个需要compact到下层的SSTfile。只会在score>=1的level里找。score的计算见VersionStorageInfo::ComputeCompactionScore({%post_linkStorage/'RocksDB代码分析——Compa......
  • RocksDB代码分析——Compaction流程
    这里从DBImpl::MaybeScheduleFlushOrCompaction开始讲起。DBImpl::MaybeScheduleFlushOrCompaction可能会scheduleDBImpl::BGWorkFlush和DBImpl::BGWorkCompaction。这里主要看Compaction。Flush部分见{%post_linkStorage/'RocksDB代码分析——Flush流程'%}DBImpl::BGWorkCo......
  • Linux查看固态盘总写入量等信息
    sudoaptinstallgsmartcontrol然后smartctl命令就有了。先尝试直接打开gmartcontrol(通过终端或者启动器)结果发现看不了。这时可以使用smartctl命令查看。首先找到固态盘的设备名。在终端中输入ls/dev/nvm*第一个就是固态盘的设备名。然后输入sudosmartctl-a/dev/......
  • 微服务JSR303解析部署使用全流程
    目录1、什么是JSR303校验2、小试牛刀【2.1】添加依赖【2.2】添加application.yml配置文件修改端口【2.3】创建实体类User【2.4】创建控制器【2.5】创建启动类【注意】不必创建前端页面3、规范返回值格式:3.1添加ResultCode工具类3.2添加Result类3.3添加ValidationEx......
  • 开源电商系统启航电商ERP系统几个核心流程的设计说明
    1、订单拉取流程开放平台拉取订单模块消息队列订单处理模块拉取订单请求订单数据发送订单通知......
  • 智慧充电平台/充电桩管理系统/小程序/APP的开发流程
    智慧充电平台开发方案旨在打造一个集充电设施管理、用户服务、数据分析与优化于一体的综合性平台,以提升电动汽车充电的便捷性和效率。以下是一个详细的开发方案概述:一、需求分析‌市场与用户调研‌:了解当前电动汽车充电市场的现状、发展趋势。收集用户对充电设施的需求、使......
  • 智慧停车道闸管理系统开发流程
    智慧停车管理平台开发方案是一个综合性的项目,旨在通过技术手段优化停车资源的分配和管理,提升停车效率和用户体验。以下是一个详细的开发方案概述:一、需求分析‌市场与用户调研‌:首先进行市场调研,了解当前智慧停车市场的现状、用户需求、竞争对手情况等信息。同时,通过问卷调......
  • Android拨号流程
    Android拨号流程是一个涉及多个组件和层级的复杂过程,从用户点击拨号按钮开始,直到电话被拨出并显示在通话界面上。以下是Android拨号流程的主要步骤:1.用户交互阶段用户通过Dialer应用(如Phone应用)的拨号界面输入电话号码,并点击拨号按钮。这一操作会触发DialpadFragment中的onClick事......