OceanBase 源码解读(十四):集群位置信息的存储与汇报

2024年 5月 7日 71.0k 0

OceanBase 源码解读(十四):集群位置信息的存储与汇报-1

本文作者:镇楠,OceanBase 内核研发工程师,对于分布式集群中副本位置信息的管理方法有着丰富的理解。

在前文源码解读第13篇《一号表》中我们为大家介绍了 __all_core_table 的定义以及其对应的内容,本文我们将聚焦在《集群位置信息的存储与汇报》上,为大家解读 OceanBase 集群 location 发现过程、__all_core_table 的位置以及 location 汇报机制。

1 OceanBase 集群的 location 发现过程

思考这样一个问题:在单机数据库中,数据库中的表都存储在本地,但在 OceanBase 这样的分布式数据库中,一张实体表可能存在多个分区,每个分区又有多个副本,分散在集群中的多个 server 上。那么当用户想去查询一张实体表时,数据库内部如何在众多 server 上定位这张表呢?

OceanBase 依靠内部的一套系统表来实现实体表的位置发现过程,这套系统表我们一般统称为 meta table。

OceanBase 源码解读(十四):集群位置信息的存储与汇报-2

涉及 location 的 meta table 主要包括 __all_core_table、__all_root_table、__all_tenant_meta_table 三张内部表。OceanBase 集群中所有实体表的 location(位置信息),以分区副本为粒度,记录在该层级关系中。

从下往上看:

1)用户表的 partition 的 replica 位置信息记录在该租户的内部表 __all_tenant_meta_table 中;

2)每个租户的 __all_tenant_meta_table 的位置信息、系统表(包括用户租户和系统租户的)位置信息记录在 __all_root_table 中;

3)__all_root_table 的位置信息记录在 __all_core_table 中;

4)__all_core_table 的位置信息存储在 RS 所在机器的内存中。

之所以设计成层级结构,一是易于维护,二是可以存储更多的实体表信息。当集群启动、实体表的分区副本变更时,都会将 location 信息主动汇报到 meta table 中。通过维护并查询这个层级结构,数据库内部就能够确定每一个实体表的位置所在。

2 meta table 的更新

OceanBase 源码解读(十四):集群位置信息的存储与汇报-3

meta table 的更新与查询都是通过 ObPartitionTableOperator 实现。ObPartitionTableOperator 会根据实体表的 table_id,调用不同的 ObPartitionTable 进行处理,然后再交给 ObPartitionTableProxy 执行更新/查询的具体操作。

2.1 __all_core_table 的位置

__all_core_table 作为1号表,是 OceanBase 集群自举与服务发现的关键。

__all_core_table leade r 的位置在集群启动时就已经确定了。

RS 的 bootstrap 过程中,需要输入 rs_list,该 rs_list 中会包括每个 zone 的一个 server 地址(IP:port)。例如:

ZONE='ZONE1' SERVER='10.232.144.13:2209', ZONE='zone2' SERVER='10.244.4.14:2203',ZONE='zone3' SERVER='10.244.4.15:2203' 

prepare_bootstrap 过程中,会在 rs_list 中的 server 上创建 __all_core_table 的 partition,并选择一个合适的 server 作为 __all_core_table 的 leader。(所谓合适的 leader,通过 primary zone 的形式指定偏好位置,但底层可能由于异常原因通过无主选举返回另一 leader,因此 prepare_bootstrap 中会 create_partition 后会通过循环监测 replica 的 to_leader_time 的形式,等待选举完成,确定真实 leader)最后会发送 RPC 到该 leader 上 execute_bootstrap,启动 RS。

其他 server 如何寻找 __all_core_table 的 leader?

每个 OceanBase server 会有一个 RsMgr ,在内存中维持 master rs 的位置信息。而 __all_core_table 的副本位置信息都存放在 rs 的内存中。其他 server 通过 rpc 的方式,到 master_rs_中拿取 partition_info。若拿取失败,则代表当前内存状态落后,会触发一套多层的刷新寻址过程:

(核心函数:int ObRpcPartitionTable::fetch_root_partition_v2(ObPartitionInfo &partition_info))

  1. 调用 RsMgr 的接口,通过 ObInnerConfigRootAddr 从本地配置项中获取 rootservice_list,并在其中遍历寻找 master_rs。(遍历优化为 rpc 询问各个 server,通过其 partition service 查询 partition leader;rs_list 变化通过心跳刷新并持久化到本地)
  2. 通过 partition service 获取 leader 和 memberlist(leader 无效则在 memberlist 中找一遍)(observer 上有 replica 就能拿到 memberlist )
  3. 在 config 中的 all_server_list 中查找

除以上方式外,RS 还会通过心跳机制,检查 observer 的状态,若10s以上无心跳,则认为该 server 的租期超时,向其主动广播自己的位置(broadcast_rs_list)。

2.2 location 汇报机制

汇报是各 observer 向 meta 表更新本机的 replica 相关信息的过程,各 partition 的 location 信息就包含其中。

2.2.1 什么时候汇报?

  1. ObService 启动时,server 主动向RS汇报自身所有 partition 信息
  2. 创建 partition
  3. partition 的 leader 发生变化时,通过回调函数的形式触发汇报
  4. RS 主动让 server 汇报
  5. meta table 迁移
  6. 其他...

2.2.2 汇报什么?

以 __all_root_table 为例,系统表需要向其全量汇报的内容包括该表的所有列,其中包含的 svr_ip、svr_port(sql_port)就是核心 location 信息:

+-----------+---------------+--------------+----------------+----------+----------+---------+---------------+-------+------+---------------------------------------+-----------+-----------+--------------+---------------+--------------+-----------------+--------------------+--------------------+-------------+---------+--------------+---------------+-----------------------+------------+--------------------+--------+-----------+--------------------+------------------+------------------+
| tenant_id | table_id      | partition_id | svr_ip         | svr_port | sql_port | unit_id | partition_cnt | zone  | role | member_list                           | row_count | data_size | data_version | data_checksum | row_checksum | column_checksum | is_original_leader | is_previous_leader | create_time | rebuild | replica_type | required_size | status                | is_restore | partition_checksum | quorum | fail_list | recovery_timestamp | memstore_percent | data_file_id     |
+-----------+---------------+--------------+----------------+----------+----------+---------+---------------+-------+------+---------------------------------------+-----------+-----------+--------------+---------------+--------------+-----------------+--------------------+--------------------+-------------+---------+--------------+---------------+-----------------------+------------+--------------------+--------+-----------+--------------------+------------------+------------------+
|         1 | 1099511627779 |            0 | 100.81.215.214 |    21100 |    21101 |       1 |             0 | zone1 |    1 | 100.81.215.214:21100:1625130315574320 |         0 |         0 |            1 |             0 |            0 |                 |                  0 |   1625130317425721 |           0 |       0 |            0 |             0 | REPLICA_STATUS_NORMAL |          0 |                  0 |      1 |           |                  0 |              100 | 1625130308620639 |
|         1 | 1099511627779 |            1 | 100.81.215.214 |    21100 |    21101 |       1 |             0 | zone1 |    1 | 100.81.215.214:21100:1625130315575073 |         0 |         0 |            1 |             0 |            0 |                 |                  0 |   1625130317425986 |           0 |       0 |            0 |             0 | REPLICA_STATUS_NORMAL |          0 |                  0 |      1 |           |                  0 |              100 | 1625130308620639 |
|         1 | 1099511627779 |            2 | 100.81.215.214 |    21100 |    21101 |       1 |             0 | zone1 |    1 | 100.81.215.214:21100:1625130315575862 |         0 |         0 |            1 |             0 |            0 |                 |                  0 |   1625130317426233 |           0 |       0 |            0 |             0 | REPLICA_STATUS_NORMAL |          0 |                  0 |      1 |           |                  0 |              100 | 1625130308620639 |
+-----------+---------------+--------------+----------------+----------+----------+---------+---------------+-------+------+---------------------------------------+-----------+-----------+--------------+---------------+--------------+-----------------+--------------------+--------------------+-------------+---------+--------------+---------------+-----------------------+------------+--------------------+--------+-----------+--------------------+------------------+------------------+

系统表的汇报过程均为全量汇报。

但是百万分区情况下,用户表需要汇报的副本数量巨大,针对 leader 切换、无主选举等场景,只向上汇报 leader 信息可有效提高感知 leader 的速度。因此针对用户表,将全量汇报优化为 role 汇报和非 role 汇报两部分。role 汇报只让 leader 更新 role 和 to_leader_time(is_previous_leader)两列信息。

2.2.3 汇报的实现

OceanBase 源码解读(十四):集群位置信息的存储与汇报-4

通过任务队列的方式,异步汇报副本信息,其中通过队列分类区分任务处理的优先级,并且进行批量处理的优化。例如 core_table_queue 中存放需要 __all_core_table 和 __all_root_table 的汇报任务,优先单独处理每个 task。user_table_queue 中存放用户表的汇报任务,进行批量处理优化。

OceanBase 源码解读(十四):集群位置信息的存储与汇报-5

role 汇报时,leader 不仅汇报自身 role 和 to_leader_time ,还会将其他副本的 role 全部更新为 follower ,因此只需要 leader 进行汇报,follower 副本不向 meta table 汇报。

全量汇报时,leader 开启事务修改 meta table ,为保证 leader 的正确性和唯一性,会比较 to_leader_time,并将其他副本的 role 更改为 follower。若此时 follower 汇报,会产生锁冲突。若发生汇报冲突,汇报任务失败后重新放入任务队列进行重试。

————————————————

(未完待续)

附录:前十三篇可参考:

1、OceanBase 数据库源码解读(一)引言

2、OceanBase 数据库源码解读(二)目录结构

3、OceanBase 源码解读(三)SQL 的一生

4、OceanBase 源码解读(四)分区的一生

5、OceanBase 源码解读(五)事务的一生

6、OceanBase 源码解读(六)租户的一生

7、OceanBase源码解读(七)带你看透虚拟表

8、OceanBase源码解读(八)OceanBase 高性能执行引擎

9、OceanBase源码解读(九)TableAPI 和 OceanBase 多模型

10、OceanBase 源码解读(十)分布式事务

11、OceanBase 源码解读(十一):表达式和函数

12、OceanBase 源码解读(十二):事务日志的提交和回放

13、OceanBase 源码解读(十三):一号表

最后的最后,您有任何疑问都可以通过以下方式联系到我们~

联系我们

欢迎广大 OceanBase 爱好者、用户和客户随时与我们联系、反馈,方式如下:

社区版官网论坛

社区版项目网站提 Issue

钉钉群:33254054

OceanBase 源码解读(十四):集群位置信息的存储与汇报-6

相关文章

Oracle如何使用授予和撤销权限的语法和示例
Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
社区版oceanbase安装
Oracle 导出CSV工具-sqluldr2
ETL数据集成丨快速将MySQL数据迁移至Doris数据库

发布评论