本文为 OceanBase 数据库源码解读系列文章的第二篇,主要介绍 OceanBase 数据库代码的整体架构和模块构成,以及各模块分别是做什么的。
顶层目录
上图为顶层目录。主体代码在 src
目录下,单元测试代码在 unittest
目录下。unittest
目录下单测的目录结构与 src
目录下的结构和命名方式相同。例如,src/sql/abc.cpp
对应的单测文件是 unittest/sql/test_abc.cpp
。单测使用 gtest 和 gmock 框架。unittest
目录下也包含一些重要组件的集成测试。
test
目录下是系统测试,这里的测试对象是完整启动的 observer。其中 test/mysql_test
目录下包含的各种测试用例是利用修改后的 mysql_test 框架运行的测试用例。它主要用 SQL 来测试系统功能正确性。
cmake
目录和 build.sh
脚本编译相关,我们将在另外一篇文章中详细介绍。
deps 目录
deps
目录比较特别,它包含 src
所依赖的东西。deps/3rd
目录包含一组工具,用来下载和编译第三方库,是专门为社区版做的。deps/easy
是一个叫做 libeasy 的 rpc 框架,它是基于 libev 的,是阿里的多隆大神早年间开发的,我们做了一些修改,现在随着 OceanBase 开源了。OceanBase 的 rpc 框架是基于 easy 的。deps/oblib
是最核心的基础库。为什么放到这里呢?因为它经过多次与 OceanBase 代码仓库的分分合合。
oblib 目录
一般情况下,oblib 库不依赖于 OceanBase src,只被依赖。rpc 是 OceanBase 业务代码所使用的内部 rpc 框架,它依赖于 libeasy,提供了一组方便的宏来快捷定义 rpc。lib
目录是依赖的最底层,它没有外部依赖,包含了错误码定义、容器类、内存分配器等大量基础类,以及最基础的头文件 ob_define.h
(想喝咖啡时你可以改一下这个文件然后执行 make。一般情况下,oblib
目录下的代码,特别是 oblib/src/lib
下的代码是与 OceanBase 业务代码无关的。也就是说,如果你在做一个其他的 C++ 项目,也可以直接使用这个库。注意,OceanBase 的编码规范要求不使用 STL 容器,所以这里有大量的“轮子”。common
目录下的代码依赖于 lib,但是比顶层 src
又更业务无关一些。如果你做一个存储系统(即使不是数据库),可能用的到这里的公共类。这里面最重要的类是 ob_object.h
中的 ObObj 表示一个包含类型信息的值。比如新增列类型就要改这个类。
接下来重点介绍 deps/oblib/src/common
目录下的几个子目录。object
目录下是最重要的数据类型 ObObj 的定义,OceanBase 支持的列数据类型,这从枚举类型 ObObjType 中可以看出来。可以看出 36 以后是 Oracle 租户类型下的数据类型。ObObj 是存储和数据处理的“原子”。rowkey
目录下定义的 ObRowkey 是每一行记录的主键。OceanBase 在底层存储只有索引组织表,每一行必须有主键;用户可见的无主键表是通过一个隐藏的自增列做 rowkey的,算是一个模拟。存储引擎的 memtable 和 sstable 中都是用 rowkey 索引的。row
目录下定义了一行记录的表示 ObNewRow (你找不到ObRow:),他是数据处理的“分子”,基于它定义的 ObRowIterator 是很多操作类的接口。
log
目录定义了一组很好用的日志宏。OceanBase 代码里面到处都有的 LOG_WARN
等宏就是在 ob_log.h
提供的。它的接口综合了 printf 和 cout 的优点,没有 cout 那么丑,又是强类型的,且限定了统一的 key-value 风格。为了在 C++ 老版实现这组接口,我们用了很多模板和宏的奇技淫巧。如果你先熟悉这组接口,再尝试贡献代码,你会爱上他们(这可是调试分布式系统的“小米加步枪”)。
src 目录
终于轮到了 src
目录。
election
是分布式选举模块,它是比较独立的,因为在运行时如果选举不出 1 号 leader,系统所有组件就都不工作。它是独立于 Paxos 协议的。该选举协议要求各节点时钟同步。clog
最初的意思是 commitlog,现在成了专有词汇,特指 OceanBase 的事务 redo 日志。Paxos 的实现也在这个目录下。archive
是日志归档组件,备份恢复依赖这个组件。
rootserver
目录是 OceanBase 集群总控服务。这个命名不够准确,准确的名字应该是 rootservice
,它不是独立进程,而是某些 observer 内部启动的一组服务,感兴趣的读者可以看看 OceanBase 0.4 的开源代码。集群管理和自动容灾,系统自举,分区副本管理和负载均衡,以及 DDL 的执行都在这个组件中。
share
目录是被强行从“母体”oblib/src/common
中剥离出来的公共类,所以它们的 namespace 是 common 而不是 share。
sql
就是 SQL。storage
就是存储引擎。事务管理位于 storage/transaction
下。
observer
是所有组件的“总装车间”,入口是 ob_server.h
和 ob_service.h
。MySQL 协议层的命令处理入口位于 observer/mysql
。