OceanBase选择了强一致性,主UpdateServer往备UpdateServer同步操作日志,如果同步成功,主UpdateServer操作本地后返回客户端更新成功,否则,主UpdateServer会把备UpdateServer从同步列表中剔除。另外,剔除备UpdateServer 之前需要通知RootServer,从而防止RootServer将不一致的备UpdateServer 选为主UpdateServer。
如下所示,主UpdateServer往备机推送操作日志,备UpdateServer的接收线程接收日志,并写人到一块全局日志缓冲区中。备UpdateServer只要接收到日志就可以回复主UpdateServer同步成功,主UpdateServer接着更新本地内存并将日志刷到磁盘文件中,最后回复客户端写入操作成功。这种方式实现了强一致性,如果主UpdateServer出现故障,备Updatcserver包含所有的修改操作,因而能够完全无量地切换为主Updateserver继续提供服务。另外,主备同步过程中要求主机刷磁盘文件,备机只需要写内存缓冲区,强同步带来的额外延时也几乎可以忽略。
OceanBase引入多版本并发控制机制后,UpdateServer备机支持多线程并发回放日志功能。如上图所示,有一个日志分发线程每次从日志源读取一批日志,拆分为单独的日志回放任务交给不同的日志回放线程处理。一批日志回放完成时,日志提交线程会将对应的事务提交到内存表并将日志内容持久化到日志文件。
class ObLogReplayWorker
{
public:
//提交一批待回放的操作日志
// @param [out]task_id 最后一条操作日志的编号
//@param [in] buf 日志缓冲区
// @param [in]len 日志缓冲区的大小
//@paran [in]replay_type 日志回放类型,包话RT_LOCAL(回放本地日志)和RT_APPLY(回放通过网络接收到的日志)
int aubmit_batch(int64_t4& task_id, const char* buf, int64_t len, const ReplayType replay_type);
public:
//需放一条操作日志
int handle_apply(ObLogTask* task);
};
备UpdateServer 有专门的日志回放线程不断地调用ObUpsLog-Mgr中的replay_log函数获取并回放操作日志。UpdateServer 支持多线程并发写事务后,replay log函数实现成调用ObLogReplay Worker中的submit_batch,将一批待回放的操作日志加入到回放任务队列中。多个日志回放线程会取出回放任务并不断地调用Handle_apply回放操作日志,即首先将操作日志预提交到MemTable中,接着加入到提交任务队列。另外,还有一个单独的提交线程会从提交任务队列中一次取出一批任务,提交到MemTable并持久化到日志文件中。