Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

StorageGroupProsessor → VirtualStorageGroupProsessor 虚拟存储组


合并的整体流程

Image Added

合并任务管理器CompactionTaskManager

...

    1. 若两个任务一个是空间内合并,另一个是跨空间合并,且系统预设的合并优先级不是balance
      1. 若系统预设的合并执行优先级是inner_cross,则空间内合并的任务的优先级较高
      2. 若系统预设的合并执行优先级是cross_inner,则跨空间合并的任务的优先级较高
    2. 若两个任务都是空间内合并
      1. 若两个任务一个是顺序空间内合并,另一个是乱序空间内合并,则顺序空间内合并的任务的优先级较高

        顺序空间内合并 > 乱序空间内合并

      2. 若两个任务的平均每个待合并文件的空间内合并次数不相等,则平均每个文件空间内合并次数低的任务的优先级较高(因为这样可以减少写放大)优先合并【低层文件(空间内合并次数低的)】:若两个任务的平均每个待合并文件的空间内合并次数不相等,则平均每个文件空间内合并次数低的任务的优先级较高(因为这样可以减少写放大)

      3. 若两个任务的选中待合并文件的数量不同,则文件数量多的任务的优先级较高优先合并【文件数量多的】:可以减少大量文件若两个任务的待合并文件的总大小不同,则待合并文件总大小较小的任务的优先级较高(因为小文件的合并速度较快)

      4. 优先合并【待合并文件总大小小的】:(因为小文件的合并速度较快)

      5. 若两个任务的待合并文件的最大version不同,则较大version的任务的优先级高(因为我们想要优先合并最近落盘的文件)优先合并【新文件】:若两个任务的待合并文件的最大version不同,则较大version的任务的优先级高(因为我们想要优先合并最近落盘的文件)

    3. 若两个任务都是跨空间合并
      1. 若两个任务的待合并的顺序文件的数量不一样,则顺序文件数量较少的任务的优先级高(因为在合并过程中占用更少的内存)优先合并【顺序文件少的】:若两个任务的待合并的顺序文件的数量不一样,则顺序文件数量较少的任务的优先级高(因为在合并过程中占用更少的内存)

      2. 乱序文件数量较多的任务的优先级较高(因为会减少更多的乱序文件)


合并任务调度器CompactionSchedule

...

    • tryToSubmitCrossSpaceCompactionTask (顺序文件链表, 乱序文件链表,…)
    • tryToSubmitInnerSpaceCompactionTask(顺序文件链表,isSeq=true…)
    • tryToSubmitInnerSpaceCompactionTask (乱序文件链表,isSeq=false…)
      • tryToSubmitInnerSpaceCompactionTask (文件链表, isSeq, …): 返回是否选中文件做合并
    • if ((无需执行顺序合并: isSeq && !enable_seq_space_compaction) || (无需执行乱序合并: !isSeq && !enable_unseq_space_compaction))
      • return false
    • 获取空间内合并的文件选择器AbstractInnerSpaceCompactionSelector
    • return innerSpaceCompactionSelector.selectAndSubmit()
      • tryToSubmitCorssSpaceCompactionTask (顺序文件链表, 乱序文件链表, …): 返回是否选中文件做合并
    • if (无需跨空间合并:!enable_cross_space_compaction)
      • return false
    • 获取跨空间合并的文件选择器AbstractCrossSpaceCompactionSelector
    • return crossSpaceCompactionSelector.selectAndSubmit()

...

合并任务的文件选择器AbstractCompactionSelector

根据一定的策略选择待被合并的一批批TsFile文件,并为每批TsFile文件创建一个合并任务放入合并任务管理器CompactionTaskManager的任务等待队列里。

空间内合并是从低层向高层搜索某层若满足连续10个文件或文件总大小超过2G则将该批文件封装到一个合并任务里,因此一次搜索某层可能出现好几批待合并文件,分别封装成好几个合并任务;跨空间合并则是针对该虚拟存储组下该时间分区下的所有乱序文件与其有Overlap的顺序文件都封装在一个合并任务里,具体判断是否有Overlap的方法是:遍历每个乱序文件里的每个ChunkGroup,在将该乱序ChunkGroup的结束时间依次与每个顺序文件的该设备ChunkGroup的结束时间做比较,若小于则说明该乱序文件与当前遍历到的顺序文件有Overlap。

无论是空间内还是跨空间合并在选择文件的时候都没有读取对应的.mods文件判断数据是否被删除。

空间内合并的文件选择器AbstractInnerSpaceCompactionSelector

...

  1. 重要属性
    1. sequenceFileResources:顺序文件链表,存放着该虚拟存储组下的该时间分区下的所有顺序文件。
    2. unsequenceFileResources:乱序文件链表,存放着该虚拟存储组下的该时间分区下的所有乱序文件。
    3. taskFactory:任务工厂,负责为每批待合并的TsFile创建一个合并任务
  2. 主要流程
    • 从虚拟存储组下该时间分区里的所有顺序和乱序文件中,选取“候选文件”:
      • 候选顺序文件:过滤掉isNotExistisDeleteisOverTTL的文件。
      • 候选乱序文件:从第一个文件开始

       

      ...

            • 若遇到isNotExist || isDelete || isOverTTL 的则跳过
            • 若遇到 isCompacting || isCompactionCandidate || isNotClosed 则返回
            • 否则添加到候选乱序文件中
        • 在指定的时间内(30s)选取“源文件”,即从候选文件中选取与乱序文件有重叠的顺序文件:
          • 遍历乱序文件,寻找与该乱序文件有重叠的所有顺序文件:(使用loose评估内存)
            • 若顺序文件中不存在isCompactingisCompactionCandidate的,则检查并用评估它们在合并中的内存开销是否超过阈值,若否,则将该批乱序和对应的顺序文件放入源文件中
            • 若顺序文件中存在一个及以上isCompactingisCompactionCandidate的,则丢弃该乱序和对应的顺序文件,并停止选取源文件。
          • 若选取的乱序文件数量为0,则使用tight评估重新选取源文件
        • 若源顺序文件或者源乱序文件列表中有一个为0,则放弃此合并任务。否则对所有的源文件set isCompactionCandidatetrue,并把该任务丢进等待队列里。

       

      RewriteCrossSpaceCompactionSelector选择器

      1. 重要方法

      1)selectAndSubmit():返回是否找到文件并提交合并任务

      ...

      文件选择器ICrossSpaceMergeFileSelector

      ...

      RewriteCompactionFileSelector

      下面详细介绍选择待合并文件的方法:

      1.   select()方法:返回的数组里第一个元素是待合并的顺序文件列表,第二个元素是待合并的乱序文件列表

      ...

      具体流程:将与该unseqFile乱序文件有Overlap的并且还未被此次合并任务文件选择器选中的顺序文件的索引放入tmpSelectedSeqFiles列表里。具体判断是否有Overlap的做法是:依次遍历获取乱序文件的每个设备ChunkGroup,判断所有还未被此次合并任务选中的顺序文件的该设备ChunkGroup是否有与乱序的ChunkGroup重叠,有的话则选中此顺序文件。

       

      MaxSeriesMergeFileSelector


      合并任务的恢复

      IOTDB-Server重启后,每个StorageGroup会执行顺序空间和乱序空间内的合并恢复和跨空间的合并恢复。

      ...

      recoverInnerSpaceCompaction(isSeq)方法:对该存储组下的每个时间分区里的每个合并日志创建一个空间内合并恢复线程SizeTieredCompactionRecoverTask,并异步执行恢复流程。,并同步执行恢复流程。

      2)跨空间合并恢复

              InitCompactionrecoverCrossSpaceCompaction()方法:往合并任务管理器CompactionTaskManager的执行线程池taskExecutionPool里提交一个跨空间合并恢复线程CompactionRecoverTask并异步执行,执行完后就会回调submitTimedCompactionTask()方法以定时执行合并任务。方法:对该存储组下的每个时间分区里的每个合并日志创建一个空间内合并恢复线程RewriteCrossCompactionRecoverTask,并同步执行恢复流程。


      合并任务的定时执行

      当server启动后,每个虚拟存储组首先会执行顺序空间和乱序空间内的合并恢复和跨空间的合并恢复,执行完后就会回调submitTimedCompactionTask()方法以定时执行合并任务,具体操作如下:

      (1) 从该虚拟存储组下的每个时间分区里依次使用合并任务调度器CompactionSchedule根据合并策略去选择一批批待合并文件,并为每批文件创建一个合并任务线程放进CompactionTaskManager里的线程等待队列里

      (2) 从等待队列里获取一个合并线程并执行

      合并的加锁流程

      1. 选择待合并的源文件,并设置setCompactionCandidate(true),将它们封装入一个合并任务里,并放入等待队列中。
      2. 从等待队列里拿出来,依次对每个源文件加读锁,并检查该源文件是否Valid,若isValidsetCompacting(true),否则释放所有源文件的读锁并setCompacting(false)
      3. 执行合并,并将临时目标文件移动成最终目标.tsfile文件,生成.resource文件,合并compactionMods文件,更新内存:
        1. 给TsFileManager加写锁
        2. 更新 TsFileResourceManager,使用Sychronized移除源文件的 TsFileResource 并增加目标文件的 TsFileResource
        3. 更新TsFileManagerTsFileResourceList,移除源文件的tsfileResource,插入目标文件的tsFileResource
        4. 给TsFileManager释放写锁
      4. 依次对每个源文件释放读锁加写锁,删除源文件和日志。
      5. 对每个源文件释放写锁setCompacting(false)setCompactionCandidate(false).