OceanBase 源码解读(十二):事务日志的提交和回放
作者简介:刻晴,对同步协议、事务并发处理有着丰富理解的 OceaBase 开发工程师。
OceanBase 的 clog 日志类似于传统数据库的 REDO 日志,这个模块负责在事务提交时持久化事务数据,并实现了基于 Multi-Paxos 的分布式一致性协议。
日志模块的设计理念
与传统关系型数据库的日志模块相比,OceanBase 的日志服务主要有如下几点挑战:
通过
Multi_Paxos
替换传统的主备同步机制,进而实现系统的高可用和数据的高可靠。
需要支持全球部署,多个副本之间的网络时延达到几十甚至数百 ms。
作为分布式数据库,OceanBase 以 Partition 作为数据同步的基本单位。
单机要求支持十万量级的 Partition,在此基础上,需要支持日志数据的高效写入和读取。
同时,任何功能本身均需要考虑操作的批量化,以加速执行速度。日志服务维护副本的成员列表、Leader 等状态信息,需要为分布式系统的丰富功能提供高效的支持。
日志的一生
OceanBase 的日志模块实现了一套标准的Multi_Paxos
,保证在未发生多数派永久性故障的前提下,所有提交成功的数据均可恢复。
同时实现了乱序日志提交,保证事务之间无依赖。在下面关于 OceanBase 对Multi_Paxos
的工程实现介绍前,我们默认读者已经了解Multi_Paxos
的核心思想,如果你还不了解Multi_Paxos
,可以在微信中关注 OceanBase 官方账号【OB 小话痨】,看看我们的 paxos 小剧场。
以一个分区的一条事务日志为例,正常的流程大致如下:
1.事务层调用 log_service->submit_log
() 接口提交日志(其中携带on_succ_cb
回调指针)。
2.clog
首先为它分配log_id和submit_timestamp
,然后提交到滑动窗口中,生成一个新的log_task
,本地提交写盘,通过 RPC 将日志同步给follower
。
3.本地写盘完成时调用log_service->flush_cb()
,更新log_task
状态,标记本地持久化成功,follower
写盘成功后给leader
回ack
。
4.leader
收到ack
更新log_task
的ack_list
。
5.leader
在 4、5 两步中会统计多数派,一旦达成majority
,按顺序调用 log_task->on_success
() 回调事务,同时发送confirmed_info
消息发送给follower
并将此日志从滑动窗口中滑出。
6.follower
收到confirmed_info
消息后尝试将此日志从滑动窗口中滑出,在滑出动作中将日志提交回放。
在 Follower 上,会对已提交的日志实时进行回放。回放流程大致如下:
follower
在滑出日志时会推大每个分区内记录回放位点的submit_log_task
的对应值,这个任务会被异步的提交到一个全局线程池中等待消费。
当全局线程池消费某分区的submit_log_task
时,会将其中记录的所有待回放日志以此读盘并分配到所在分区的对应的 4 个回放任务队列中,分配的方式主要是按照trans_id
进行哈希,确保同一事务的日志被分配到一个队列中,被分配到新任务的队列将队列task_queue
作为一个任务再次异步提交到 1 中提到的全局线程池中等待消费。
当全局线程池消费task_queue
时,依次遍历队列中所有子任务并根据日志类型执行相应的应用逻辑。至此,一个日志真正的同步到了follower
中,在follower
上也可读了。
版权声明: 本文为 InfoQ 作者【OceanBase 数据库】的原创文章。
原文链接:【http://xie.infoq.cn/article/4e55bc484e1fc749585f33709】。文章转载请联系作者。
评论