如果把 OceanBase 集群比作一艘船,RootService(RS)就是驾驶舱,而 rootserver/ob_root_service.cpp 里的 ObRootService 类则是驾驶舱里的总控台。它运行在 RS Leader 节点,负责集群成员管理、租户与资源池调度、DDL 路由、心跳租约、升级、系统包加载等全局事务。与 observer 内其它子系统按租户实例化不同,RS 相关逻辑是集群级别的单例,必须在正确的时间以正确的顺序把 Server 管理、Zone 管理、Unit 管理、DDL 服务、均衡器、检查器等一系列模块装配起来。本文聚焦这个总控入口,看 OceanBase 如何用一套状态机驱动整个集群的启停与运维。
核心数据结构
ObRootService 类汇集了 RS 所需的全部子系统,关键成员如下:
class ObRootService {
bool inited_; // 是否完成 init()
bool server_refreshed_;
ObAddr self_addr_; // 本机地址
ObServerConfig *config_; // 集群配置
ObSrvRpcProxy rpc_proxy_; // 对外 RPC 代理
ObCommonRpcProxy common_proxy_; // 通用 RPC 代理
ObMySQLProxy sql_proxy_; // SQL 执行代理
ObMultiVersionSchemaService *schema_service_; // 多版本 schema 服务
ObLSTableOperator *lst_operator_; // 日志流位置表操作器
ObServerManager server_manager_; // OBServer 成员管理
ObHeartbeatChecker hb_checker_; // 心跳检查器
ObServerChecker server_checker_; // Server 状态检查器
ObZoneManager zone_manager_; // Zone 管理
ObZoneStorageManager zone_storage_manager_;
ObDDLService ddl_service_; // DDL 服务
ObTenantDDLService tenant_ddl_service_;
ObUnitManager unit_manager_; // Unit 资源管理
ObRootBalancer root_balancer_; // 负载均衡
ObRootInspection root_inspection_; // RS 巡检
ObUpgradeExecutor upgrade_executor_; // 升级执行器
ObLSTableOperator *lst_operator_; // 日志流位置表
common::ObLatch bootstrap_lock_; // 引导锁
share::ObRsStatus rs_status_; // RS 状态机
int64_t fail_count_; // 启动失败计数
...
};
其中 ObServerManager 维护所有 OBServer 的存活状态与版本;ObUnitManager 负责资源单元(CPU/内存/磁盘)的分配与迁移;ObDDLService 与 tenant_ddl_service_ 分别处理系统租户和普通租户的 schema 变更;ObLSTableOperator 提供日志流位置信息,是 RS 高可用与副本定位的基础;rs_status_ 则驱动 RS 自身的生命周期状态机。
生命周期三阶段
init:装配依赖,但不激活
init() 是 RS 的真实初始化入口。它按”先本地队列与元数据,再 Server/Zone/Unit,最后 DDL 与检查器”的顺序依次初始化 20 多个子系统。所有 RPC 代理在此阶段保持 inactive,避免未就绪的 RS 提前对外暴露服务:
int ObRootService::init(ObServerConfig &config, ObConfigManager &config_mgr,
ObSrvRpcProxy &srv_rpc_proxy, ObCommonRpcProxy &common_proxy,
ObAddr &self, ObMySQLProxy &sql_proxy,
observer::ObRestoreCtx &restore_ctx, ObRsMgr &rs_mgr,
ObMultiVersionSchemaService *schema_service,
ObLSTableOperator &lst_operator)
{
// 参数校验:地址合法、schema_service 非空
if (inited_) { ret = OB_INIT_TWICE; }
else if (!self.is_valid()) { ret = OB_INVALID_ARGUMENT; }
else if (NULL == schema_service) { ret = OB_INVALID_ARGUMENT; }
else {
config_ = &config; config_mgr_ = &config_mgr;
rpc_proxy_ = srv_rpc_proxy; common_proxy_ = common_proxy;
const bool rpc_active = false; // init 阶段不激活 RPC
common_proxy_.active(rpc_active);
rpc_proxy_.active(rpc_active);
self_addr_ = self; restore_ctx_ = &restore_ctx;
sql_proxy_.assign(sql_proxy); sql_proxy_.set_inactive();
// oracle 代理也设为 inactive
rs_mgr_ = &rs_mgr;
addr_agent_ = &rs_mgr.get_addr_agent();
schema_service_ = schema_service;
lst_operator_ = &lst_operator;
}
// 子系统初始化:任务队列、Zone、Server、DDL、Unit、均衡、巡检...
if (FAILEDx(task_queue_.init(...))) { ... }
else if (OB_FAIL(zone_manager_.init(sql_proxy_))) { ... }
else if (OB_FAIL(server_manager_.init(...))) { ... }
else if (OB_FAIL(ddl_service_.init(...))) { ... }
else if (OB_FAIL(tenant_ddl_service_.init(...))) { ... }
else if (OB_FAIL(unit_manager_.init(...))) { ... }
else if (OB_FAIL(root_balancer_.init(...))) { ... }
else if (OB_FAIL(root_inspection_.init(...))) { ... }
else if (OB_FAIL(upgrade_executor_.init(...))) { ... }
...
if (OB_SUCC(ret)) { inited_ = true; }
return ret;
}
瀑布式错误处理让失败位置一目了然;任意子系统初始化失败都会打印 DBA 级日志,便于运维快速定位。
start_service:从 Leader 开始对外服务
start_service() 只有在当前节点是 RS Leader 时才执行。它把 rs_status_ 从 INIT 推到 STARTING,激活 RPC 与 SQL 代理,启动心跳检查器与异步任务队列,注册 LS 表回调,并调度后续定时任务:
int ObRootService::start_service()
{
start_service_time_ = ObTimeUtility::current_time();
if (!inited_) { ret = OB_NOT_INIT; }
else if (OB_FAIL(rs_status_.set_rs_status(status::STARTING))) { ... }
else if (!ObRootServiceRoleChecker::is_rootserver()) { ret = OB_NOT_MASTER; }
else {
sql_proxy_.set_active(); oracle_sql_proxy_.set_active();
const bool rpc_active = true;
common_proxy_.active(rpc_active); rpc_proxy_.active(rpc_active);
tenant_ddl_service_.restart();
server_manager_.reset(); zone_manager_.reset();
if (OB_FAIL(hb_checker_.start())) { ... }
else if (OB_FAIL(task_queue_.start())) { ... }
else if (OB_FAIL(inspect_task_queue_.start())) { ... }
else if (OB_FAIL(TG_START(lib::TGDefIDs::GlobalCtxTimer))) { ... }
else if (OB_FAIL(global_ctx_task_.schedule(...))) { ... }
else if (OB_FAIL(lst_operator_->set_callback_for_rs(rs_list_change_cb_))) { ... }
else if (OB_TMP_FAIL(update_inmemory_ls_table_())) { /* 加速启动,忽略 */ }
if (FAILEDx(rs_status_.set_rs_status(status::IN_SERVICE))) { ... }
else if (OB_FAIL(schedule_refresh_server_timer_task(0))) { ... }
else if (OB_FAIL(schedule_restart_timer_task(0))) { ... }
}
if (OB_FAIL(ret)) {
update_fail_count(ret);
rs_status_.set_rs_status(status::STOPPING);
stop_service(); // 启动失败自动回滚
}
return ret;
}
这里有两个关键设计:一是 ObRootServiceRoleChecker 保证只有 Leader 才进入 IN_SERVICE,避免脑裂;二是启动失败时自动回滚到 STOPPING 并调用 stop_service(),防止半启动状态对外提供服务。
stop_service:优雅停机与状态重置
stop_service() 是 RS 的停机入口,先停线程,再等待结束,最后把状态重置为 INIT,为后续重新启动或销毁做准备:
int ObRootService::stop_service()
{
if (OB_FAIL(stop())) { LOG_WARN(...); }
else { wait(); }
if (FAILEDx(rs_status_.set_rs_status(status::INIT))) { ... }
return ret;
}
集群启动:execute_bootstrap
execute_bootstrap() 是集群首次启动时的”开机向导”,串联起系统租户、日志流、Unit 与系统包的创建:
int ObRootService::execute_bootstrap(const obrpc::ObBootstrapArg &arg)
{
const ObServerInfoList &server_list = arg.server_list_;
if (server_list.count() <= 0) { ret = OB_INVALID_ARGUMENT; }
else {
update_cpu_quota_concurrency_in_memory_();
ObLatchWGuard guard(bootstrap_lock_, ObLatchIds::RS_BOOTSTRAP_LOCK); // 防并发
ObBootstrap bootstrap(rpc_proxy_, *lst_operator_, ddl_service_, tenant_ddl_service_,
unit_manager_, *config_, arg, common_proxy_);
if (OB_FAIL(bootstrap.execute_bootstrap(server_zone_op_service_))) { ... }
if (OB_SUCC(ret)) {
if (OB_FAIL(load_all_sys_package())) { ... }
else if (OB_FAIL(do_restart())) { ... }
else if (OB_FAIL(check_ddl_allowed())) { ... }
else if (OB_FAIL(update_all_server_and_rslist())) { ... }
else if (OB_FAIL(zone_manager_.reload())) { ... }
else if (OB_FAIL(set_cluster_version())) { ... }
else if (OB_FAIL(finish_bootstrap())) { ... }
else if (OB_FAIL(update_baseline_schema_version())) { ... }
else if (OB_FAIL(wait_all_rs_in_service_after_bootstrap_(server_list))) { ... }
...
}
clear_special_cluster_schema_status(); // 无论成败都清理 bootstrap 标记
}
return ret;
}
流程先加 bootstrap_lock_ 防止多节点同时引导,随后调用 ObBootstrap 完成核心元数据创建,再通过 do_restart() 启动后台任务,最后等待所有 RS 进入 IN_SERVICE。每个关键步骤都带有 DBA 级日志与错误建议,运维人员可以根据错误码快速排查。
心跳纽带:renew_lease
renew_lease() 处理 OBServer 上报的心跳请求,是 RS 与集群节点保持连接的纽带。它不仅更新节点状态,还在 full_service 后把租约过期时间、schema 版本、主密钥版本等信息回传给节点:
int ObRootService::renew_lease(const ObLeaseRequest &lease_request,
ObLeaseResponse &lease_response)
{
if (!inited_) { ret = OB_NOT_INIT; }
else if (!lease_request.is_valid()) { ret = OB_INVALID_ARGUMENT; }
else if (OB_FAIL(server_manager_.receive_hb(lease_request, server_id, to_alive))) { ... }
else {
lease_response.rs_server_status_ = RSS_INVALID;
if (is_full_service()) {
zone_manager_.get_lease_info_version(lease_info_version);
server_manager_.get_server_status(lease_request.server_, server_stat);
if (!ObHeartbeatService::is_service_enabled()) {
server_manager_.is_server_stopped(lease_request.server_, is_stopped);
lease_response.rs_server_status_ = is_stopped ? RSS_IS_STOPPED : RSS_IS_WORKING;
}
}
lease_response.version_ = ObLeaseResponse::LEASE_VERSION;
construct_lease_expire_time(lease_request, lease_response, server_stat);
lease_response.server_id_ = server_id;
lease_response.baseline_schema_version_ = baseline_schema_version_;
schema_service_->get_tenant_schema_version(OB_SYS_TENANT_ID, lease_response.schema_version_);
schema_service_->get_refresh_schema_info(lease_response.refresh_schema_info_);
}
return ret;
}
心跳不仅是”探活”,更是状态同步通道:节点通过它感知 RS 是否正常工作,RS 通过它维护整个集群的 Server 列表与租约时钟。
小结
ObRootService 把原本分散在集群各处的全局能力收敛到一个类中,通过 INIT → STARTING → IN_SERVICE → STOPPING → INIT 的状态机控制所有子系统的启停顺序。init 负责装配、start_service 负责激活、stop_service 负责优雅退出、execute_bootstrap 负责集群首次创建、renew_lease 负责维持节点心跳。这种”单点总控 + 状态机驱动”的设计,让 OceanBase 在面对集群扩缩容、升级、故障恢复时,有了统一的控制平面与清晰的错误传播路径。