暂无图片
暂无图片
13
暂无图片
暂无图片
暂无图片

OceanBase的Redo日志

OceanBase 2022-09-30
995

概述

Redo 日志是 OceanBase 数据库用于宕机恢复以及维护多副本数据一致性的关键组件。Redo 日志是一种物理日志,它记录了数据库对于数据的全部修改历史,具体的说记录的是一次写操作后的结果。从某个持久化的数据版本开始逐条回放 Redo 日志可以还原出数据的最新版本。

OceanBase 数据库的 Redo 日志有两个主要作用:

  • 宕机恢复

    与大多数主流数据库相同,OceanBase 数据库遵循 WAL(write-ahead logging)原则,在事务提交前将 Redo 日志持久化,保证事务的原子性和持久性( ACID 中的 "A" 和 "D")。如果 observer 进程退出或所在的服务器宕机,重启 OBServer 会扫描并回放本地的 Redo 日志用于恢复数据。宕机时未持久化的数据会随着 Redo 日志的回放而重新产生。

  • 多副本数据一致性

    OceanBase 数据库采用 Multi-Paxos 协议在多个副本间同步 Redo 日志。对于事务层来说,一次 Redo 日志的写入只有同步到多数派副本上时才能认为成功。而事务的提交需要所有 Redo 日志都成功写入。最终,所有副本都会收到相同的一段 Redo 日志并回放出数据。这就保证了一个成功提交的事务的修改最终会在所有副本上生效并保持一致。Redo 日志在多个副本上的持久化使得 OceanBase 数据库可以提供更强的容灾能力。

日志文件类型

OceanBase 数据库采用了分区级别的日志流,每个分区的所有日志要求在逻辑上连续有序。而一台机器上的所有日志流最终会写入到一个日志文件中。

OceanBase 数据库的 Redo 日志文件包含如下两种类型:

  • Clog

    全称 Commit log,用于记录 Redo 日志的日志内容,位于 store/clog 目录下,文件编号从 1 开始并连续递增,文件 ID 不会复用,单个日志文件的大小为 64 MB。这些日志文件记录数据库中的数据所做的更改操作,提供数据持久性保证。

  • ilog

    全称 index log,用于记录相同分区相同 Log ID 的已经形成多数派日志的 Commit log 的位置信息。位于 store/ilog 目录下,文件编号从 1 开始并连续递增,文件 ID 不会复用,单个日志文件的大小非定长。这个目录下的日志文件是 Clog 的索引,本质上是对日志管理的一种优化,ilog 文件删除不会影响数据持久性,但可能会影响系统的恢复时间。 ilog 文件和 Clog 文件没有对应关系,由于 ilog 针对单条日志记录的内容会比 Clog 少很多,因此一般场景下 ilog 文件数目也比 Clog 文件数目少很多。

日志的产生

OceanBase 数据库的每条 Redo 日志最大为 2 MB。事务在执行过程中会在事务上下文中维护历史操作,包含数据写入、上锁等操作。在 V3.x 之前的版本中,OceanBase 数据库仅在事务提交时才会将事务上下文中保存的历史操作转换成 Redo 日志,以 2 MB 为单位提交到 Clog 模块,Clog 模块负责将日志同步到所有副本并持久化。在 V3.x 及之后的版本中, OceanBase 数据库新增了即时写日志功能,当事务内数据超过 2 MB 时,生成 Redo 日志,提交到 Clog 模块。以 2 MB 为单位主要是出于性能考虑,每条日志提交到 Clog 模块后需要经过 Multi-Paxos 同步到多数派,这个过程需要较多的网络通信,耗时较多。因此,相比于传统数据库,OceanBase 数据库的单条 Redo 日志聚合了多次写操作的内容。

OceanBase 数据库的一个分区可能会有 3~5 个副本,其中只有一个副本可以作为 Leader 提供写服务,产生 Redo 日志,其它副本都只能被动接收日志。

日志的回放

Redo 日志的回放是 OceanBase 数据库提供高可用能力的基础。日志同步到 Follower 副本后,副本会将日志按照 transaction_id 哈希到同一个线程池的不同任务队列中进行回放。OceanBase 数据库中不同事务的 Redo 日志并行回放,同一事务的 Redo 日志串行回放,在提高回放速度的同时保证了回放的正确性。日志在副本上回放时首先会创建出事务上下文,然后在事务上下文中还原出操作历史,并在回放到 Commit 日志时将事务提交,相当于事务在副本的镜像上又执行了一次。

日志容灾

通过回放 Redo 日志,副本最终会将 Leader 上执行过的事务重新执行一遍,获得和 Leader 一致的数据状态。当某一分区的 Leader 所在的机器发生故障或由于负载过高无法提供服务时,可以重新将另一个机器上的副本选为新的 Leader。因为它们拥有相同的日志和数据,新 Leader 可以继续提供服务。只要发生故障的副本不超过一半,OceanBase 数据库都可以持续提供服务。发生故障的副本在重启后会重新回放日志,还原出未持久化的数据,最终会和 Leader 保持一致的状态。

对于传统数据库来说,无论是故障宕机还是重新选主,正在执行的事务都会伴随内存信息的丢失而丢失状态。之后通过回放恢复出来的活跃事务因为无法确定状态而只能被回滚。从 Redo 日志的角度看就是回放完所有日志后仍然没有 Commit 日志。在 OceanBase 数据库中重新选主会有一段时间允许正在执行的事务将自己的数据和事务状态写成日志并提交到多数派副本,这样在新的 Leader 上事务可以继续执行。

日志的控制与回收

日志文件中记录了数据库的所有修改,因此回收的前提是日志相关的数据都已经成功持久化到磁盘上。如果数据还未持久化就回收了日志,故障后数据就无法被恢复。

当前,OceanBase 数据库的日志回收策略中对用户可见的配置项有 2 个:

  • clog_disk_usage_limit_percentage

    该配置项用于控制 Clog 或 ilog 磁盘空间的使用上限,默认值为 95,表示允许 Clog 或 ilog 使用的磁盘空间占总磁盘空间的百分比。这是一个刚性的限制,超过此值后该 OBServer 不再允许任何新事务的写入,同时不允许接收其他 OBServer 同步的日志。对外表现是所有访问此 OBServer 的读写事务报 "transaction needs rollback" 的错误。

  • clog_disk_utilization_threshold

    该配置项用于控制 Clog 或 ilog 磁盘的复用下限。在系统工作正常时,Clog 或 ilog 会在此水位开始复用最老的日志文件,默认值是 Clog 或 ilog 独立磁盘空间的 80%,不可修改。因此,正常运行的情况下,Clog 或 ilog 磁盘空间占用不会超过 80%,超过则会报 "clog disk is almost full" 的错误,提醒 DBA 处理。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论