与 commitlog 相关的类如下:
1. CommitLog Service 线程后台 sync
AbstractCommitLogService 类中的 start() 函数新建 SyncRunnable 线程,并运行该线程。
该线程运行的函数是 run(), run() 中不停调用 sync(). sync() 利用 parkNanos() 周期性进行 sync 操作, 但这只对 group 和 periodical 的 commitlog 有效,对于 batch 的 commitlog 会在 BatchCommitLogService 类的 maybeWaitForSync() 函数中显示调用 unpark() 唤醒线程。
2. CommitLog 构建 CommitLog Service 和 CommitLog Manager
CommitLog 类中,利用 construct() 生成一个具体的 AbstractCommitLogService 类和一个 AbstractCommitLogSegmentManager 类。
executor 是一个具体的 AbstractCommitLogService 类, PeriodicCommitLogService, BatchCommitLogService 和 GroupCommitLogService 中的一个。
segmentManager 是一个具体的 AbstractCommitLogSegmentManager 类, CommitLogSegmentManagerCDC 和 CommitLogSegmentManagerStandard 中的一个。
最后 CommitLog 调用 start() 启动 segmentManager.start() 和 executor.start()
executor.start() 也就是调用 AbstractCommitLogService 的 start() 函数启动一个线程周期性执行 sync() 操作。
segmentManager.start() 也就是调用 AbstractCommitLogSegmentManager 的 start() 函数,启动一个后台线程分配 CommitLogSegment
3. 何时写 CommitLog
运行到 1341 行时的函数栈如下图所示。1341行新建了一个线程,在1347行时运行。
beginWrite() 中调用 CommitLog.instance.add(mutation) 写入 commitlog。
运行到 CommitLog.instance.add(mutation) 时的函数栈如下:
CommitLog.instance.add() 函数实现 commitlog 的提交
4. 等待 commitlog 持久化完成
上图中的 executor.finishWriteFor(alloc) 会调用 AbstractCommitLogService 的 finishWriteFor() , 从而调用相应子类的 maybeWaitForSync()。
BatchCommitLogService 中的 maybeWaitForSync() 函数会调用 requestExtraSync() 唤醒 sync 线程进行 sync。然后调用 awaitDiskSync() 等待 commitlog 持久化完成。
GroupCommitLogService 中的 maybeWaitForSync() 函数会调用 awaitDiskSync() 等待 commitlog 持久化完成, 依赖后台 sync 线程的周期性 sync 操作。
PeriodicCommitLogService中的 maybeWaitForSync() 函数, blockWhenSyncLagsNanos 是 periodic commitlog 的周期, expectedSyncTime = System.nanoTime() - blockWhenSyncLagsNanos,表示 expectedSyncTime 之前的 commitlog 应该要持久化完。 lastSyncedAt 表示上次持久化的时间。 调用 awaitSyncAt() 等待 expectedSyncTime 之前的 commitlong 持久化完。