琐事太多,又太懒了,好久不想动笔,进展也比较慢。
5 日志系统
有伟大的GFS作指引,OceanBase的master也是采用redo log加checkpoint机制,以保证master的响应速度。此外root server采取了主备机制,因此redo log一写两份, 在flush redolog时先写slave,成功了才写master并重置log的内存缓存区。
日志系统是比较核心的一块,这块的体量也不小。慢慢看吧。
5.1 类图
首先来一张类图,列示日志系统涉及到的类,显然我们需要从ObRootLogManager这个类入手。
先来整理这几个类之间的关系,ObRootLogWorker向Root Server提供了写入各种系统log的接口,比如registerchunk server的regist_cs(),register merge server的regist_ms(),增加tablet的add_new_tablet()等等。
ObRootLogManager,如其名,日志管理器。主要就是日志系统初始化和回放log,以及做checkpoint,管理log目录等信息。
ObRootLogManager又继承了ObLogWriter,ObLogWriter是写log file的底层类。所以ObRootLogWorker写log的接口如regist_cs(),最终都是通过调用ObRootLogManager完成的,它看不到ObLogWriter。这种设计风格因人而异,最终结果大同小异。
5.2 LogManager初始化
接着上面master启动的流程,看看日志系统初始化和replay log的逻辑。初始化流程相对简单。Logmanager会在initialize时调用OpLogDirScanner扫描日志目录,取得log id和checkpoint id。
5.2.1 Scanner扫描
另外,log id和checkpoint id都是数字。Scanner将log id排序,得到最小和最大的log id,以及最大的checkpoint id,作为状态基点。
Scnner从最大id向前检查,如果碰到不连续的id,则跳出;
1 如果log文件集合为空,则设置max min log id为0,返回OK;
2 log文件id连续,最正常的情况,返回OK;
3 log文件id不连续,举个例子:2,3,5,6,7,8;那么此时在5处开始不连续了,min log id就等于5;并返回OB_DISCONTINUOUS_LOG。
5.2.2 获取扫描状态
1没有checkpoint
设置replay_point_ = 1;如果log为空,则设置max_log_id_ = 1;否则根据结果取出max log id,scanner.get_max_log_id(max_log_id_);
2 有checkpoint
scanner.get_max_ckpt_id(ckpt_id_),合法性检查,如果min log id > ckpt_id_+1,则表明有错误;
设置replay_point_ = ckpt_id_ + 1;
后面从checkpoint恢复后,master还将从id为replay_point_的l