design notes
这篇文章解释了RowSet的flush、compaction执行过程。如果为了了解compaction是的选择策略,请参考compaction-policy.md文档。注意,这里也不介绍delta file的flush过程。
目标:执行update的同时,把两个key range有重叠的RowSet,合并成一个RowSet。合并后的RowSet会回收合并前Rowset中被delete的数据行。
举个简单的例子:1个rowset compact to 1个新rowset。Compact执行时的removing GCable和applying update是有效的。compaction分为两个主要的阶段:
"flush_snap"
|
|
before v
<----------|
Phase 1:
merging/flushing
|-----------|
Phase 2: migrate
deltas
|---------------|
compaction
complete
|----------->
|-------------- time ----------------------------->
System steady state:准备阶段
- updated只会存入原始RowSet(source or input rowset)
到phase 1的过度阶段:
- 创建一个快照迭代器,保存输入Rowset的所有MVCC snapshot状态
Phase 1(阶段1):merge阶段
- 如上创建的迭代器中,创建一个新的output RowSet保存input RowSet数据。这对于阶段1之前的所有update和delete是有效的,而对于这个阶段过程中的update和delete是没有效果的。
- 此阶段中的任何mutation只会保存在input RowSet的delta files里。因为merge操作只针对之间的快照,所以这些mutation不会存入output RowSet。
Phase 2:迁移阶段1中的delta files
- 此阶段过程中的mutation,在input RowSet和output RowSet中都会保存。这个操作很简单,当update提交时,将key地址复制给output RowSet的key列。此操作是通过DuplicationRowSet接口实现的(update时input和output rowset多会操作)。
- 此阶段过程中的read操作指向的是input RowSet,因为output RowSet缺少merge阶段(阶段1)过程中写入的deltafile。
- 因为阶段1中的merge忽略了该阶段运行过程中接收的数据,所以,我们必须“迁移”这些mutation到output RowSet。我们可以高效的收集所有不在迭代器快照中的deltafile,然后保存到output rowset中。
Phase 2收尾:切换RowSet
- 阶段2后,output 和input RowSet 逻辑上有相同的数据,它们可以做原子级别的切换(swap)。一旦切换成功,新的update只需要保存到ouput RowSet中,老的RowSet(input)会被删除。
Extending to multiple RowSets
如上的算法,可以扩展到多个RowSet情形下。在compaction开始阶段,每个RowSet都快照起来,然后创建一个快照迭代器,按照key的上升序循环所有快照,并进行merge。