开源分布式数据库PolarDB-X源码解读——PolarDB-X源码解读(二):CN启动流程

简介: 开源分布式数据库PolarDB-X源码解读——PolarDB-X源码解读(二):CN启动流程

本文主要讲解PolarDB-X的CN节点(polardbx-sql)的启动过程包括参数加载、元信息加载等过程并对启动过程中设计的模块做简单的介绍。  


CN Server层的代码主要包含在polardbx-server模块中,main函数位于TddlLauncher


主逻辑入口在CobarServer.init()方法中。


CN启动分为以下几个流程:


1.CobarServer对象的创建


该类是单例,可以通过CobarServer.getInstance()获取。


2.参数加载


路径:TddlLauncher.main() -> CobarServer.new() -> CobarConfig.new() -> CobarConfig.initCobarConfig() -> ServerLoader.load()


CN的参数均为key-value的形式。


ServerLoader.load()中,CN主要从以下位置读取参数:


 server.properties文件,其默认位置在classpath的根目录中,所以一般使

 用           IDE          进         行            开          发          时 ,     加          载          的         是

polardbx-server\src\main\resources\server.properties文件


String conf = 
System.getProperty("server.conf","classpath:server.properties");


 Java运行参数中


例如java...-DserverPort=8527


 环境变量中


serverProps.putAll(System.getProperties());
serverProps.putAll(System.getenv());


以上参数来源中,server.properties的优先级最低,环境变量中的优先级最高,当包含同名参数时,高优先级的参数来源会覆盖低优先级的参数来源。


加载的参数,会保存在SystemConfig中,该类为单例,可以通过CobarServer.getInstance().getConfig().getSystem()获取。


3.从MetaDB读取元数据,并初始化实例级的系统组件


路径:

TddlLauncher.main()->CobarServer.new()->CobarConfig.new()->CobarConfig.initCobarConfig()->ServerLoader.load()->ServerLoader.initPolarDbXComponents()


1)初始化元数据库的连接池


MetaDbDataSource.initMetaDbDataSource


会使用SystemConfig中存储的MetaDB的地址、端口、用户名、密码、库名等信息,建立与MetaDB的连接。


MetaDbDataSource
            .initMetaDbDataSource(this.system.getMetaDbAddr(), this.system.getMetaDbName(),
                this.system.getMetaDbProp(),
                this.system.getMetaDbUser(),
                this.system.getMetaDbPasswd());


MetaDbDataSource是一个单例,实现了JDBC的程序中可以使用MetaDbDataSource.getInstance().getConnection()获取与MetaDB的连接(实现了JDBC接口),并使用该连对MetaDB进行访问。


2)对系统表进行创建或者升级


SchemaChangeManager.getInstance().handle();


polardbx-gms\src\main\resources\ddl\中保存了系统表的表结构,并且使用alter语句记录了每一次版本的变更。SchemaChangeManager在初始化时,会检测当前每个系统表的表结构版本,如果版本较老,会依次使用这些语句对alter语句进行更新。


3)读取实例ID信息


ServerInstIdManager.getInstance();


一个PolarDB-X集群也称为一个实例,在MetaDB中有一个唯一的实例ID。同时,PolarDB-X实例有主实例与只读实例两种模式。当存在只读实例时,必然存在一个主实例。该步骤从MetaDB中读取实例ID,如果当前实例为只读实例,则还会读取其主实例的实例ID。  


4)MetaDbConfigManager


先简单介绍下这个东西是干啥的。


我们存在MetaDB中的配置信息,如果发生变化,CN需要能感知到这个变化。例如,某个表增加了一个列。作为CN,如何能感知到这个变化呢?


一个比较简单的思路是对元数据做轮询,各几秒查一次。但如果让每个模块都去做这样的事情,会有个比较大的问题是对MetaDB的访问压力会很大。


MetaDbConfigManager对此作了封装,作了一个统一的轮询机制。但由于每个模块元数据表的格式千变万化,所以MetaDbConfigManager并不是直接轮询每个模块的元数据表,而是轮询config_listener这张表。这张表的几个关键列是data_id、op_version、gmt_modified。


我们可以为每个data_id在代码中注册一个listener,当MetaDbConfigManager轮询到data_id的op_version发生变化的时,会回调这个listener,一般情况下,各模块实现的listener会按需要再读取对应的元数据表。


例如,d1.t1表在config_listener中有一行记录:


polardbx.meta.table.d1.t1


往t1表中增加了一个列,我们会修改MetaDB中的columns表,同时,我们会修改config_listener表中 polardbx.meta.table.d1.t1这行记录的op_version,进行+1的操作。


几秒钟后,MetaDbConfigManager会轮询到这行记录的op_version列发生了变化,会回调表结构管理模块的listener(类:TableMetaListener),该listener会重新加载d1.t1表的元数据。


在启动时,CN会初始化MetaDbConfigManager用于做轮询的线程和定时任务。


5)MetaDbInstConfigManager


初始化实例级的配置项,这里的配置项类似于MySQL中的System Variables,例如SQL的内存大小限制之类的。该阶段会从MetaDB的inst_config表中加载所有的配置项并保存在内存中。


并且会注册对应的listener,这样当inst_config表发生变化的时候,会回调MetaDbInstConfigManager的listener。  


6)ConnPoolConfigManager


这个是用来存连接池(CN与DN之间的连接池)相关的配置项的(其实它用到的配置MetaDbInstConfigManager中都有),也是从inst_config中读取。


7)StorageHaManager


这个比较重要。


目前每一组DN(这里的组指一个Paxos组)内选举的结果是存储在该组DN自己的系统表中,并不会写到MetaDB中。因此CN需要有机制去从DN的系统表中探测各节点的角色。


StorageHaManager会从storage_info表中读取所有的DN节点的连接信息,并且内部会有轮询的线程去检测角色信息。当DN发生HA的时候,StorageHaManager会探测到这个变化,并感知到最新的Leader等角色。


8)初始化系统库


initSystemDbIfNeed初始化information_schema和polardbx等几个系统库。


4.创建线程池


路径:CobarServer.new()


几个主要的线程池的创建:


 managerExecutor,负责Manager端口的请求。

 killExecutor,专门用来执行kill指令

 serverExecutor,各种SQL都是由这个线程池执行


5.CobarServer.init


路径:TddlLauncher.main()->CobarServer.init()  


1)逻辑库(TDataSource)的初始化


入口在GmsAppLoader.initDbUserPrivsInfo,类里的“App”指的就是一个逻辑库。这里会加载每个逻辑库的用户权限信息以及最重要的TDataSouce。


TDataSource在CN中与逻辑库一一对应。它是每个逻辑库执行SQL的入口。TDatSource的初始化逻辑在MatrixConfigHolder.init中,包含了以下内容:


 初始化拓扑,例如这个库包含了哪些DN,并初始化与这些DN之间的连接池

 (TopologyHandler.initPolarDbXTopology


 获取每个DN的信息,包括版本,特性的支持程度等

StorageInfoManager.init


 初始化分片的路由信息(mode='drds',TddlRuleManager.init

 mode='auto',PartitionInfoManager.init


 初始化表管理器(有哪些表、每个表有哪些列哪些索引等)(GmsTableMetaManager.init


 初始化事务管理器(transactionManager.init()


 创建Plan Cache(PlanCache planCache = new PlanCache(schemaName);


 启动DDL任务引擎(ddlEngineInit()


 统计信息管理器的初始化(StatisticManager.init


 SPM的初始化(PlanManager.init


2)GmsClusterLoader.loadPolarDbXCluster


加载集群信息,例如集群中有哪些CN节点等。初始化CclService,这个是用来做SQL限流的。


3)warmup


CN的SQL函数目前是反射机制进行加载的,这里主要作用是加载下所有的函数。


6.网络层的初始化


该步骤结束后,服务端口便会打开,该CN进程就能开始对外提供服务了。  


CN在这一步会启动Server端口与Manager端口两个端口。  


Server端口对应MySQL的3306端口,是提供给前端应用使用的。


Manager端口用于内部的管理使用,例如,SHOW PROCEESSLIST指令需要收集所有CN的执行情况,就会使用该端口进行收集。


1)NIOProcessor


processors = new NIOProcessor[system.getProcessors()];
for (int i = 0; i < processors.length; i++) {
      processors[i] = new NIOProcessor(i, "Processor" + i,this.serverExecutor);
processors[i].startup();
}


CN网络层处理请求的入口是NIOProcessor,每个NIOProcessor有读写两个线程。这里会来启动NIOProcessor的W与R线程。


2)NIOAcceptor


CN网络层用来处理连接建立请求的是NIOAcceptor,NIOAcceptor的new过程中,会打开端口进行监听:  


public NIOAcceptor(String name, int port, FrontendConnectionFactory factory, boolean online) throws IOException {
        super.setName(name);
        ...
            this.selector = Selector.open();
            this.serverChannel = ServerSocketChannel.open();
            this.serverChannel.socket().bind(new InetSocketAddress(port), 65535);
        ...
    }


同时,NIOAcceptor也是一个线程,会处理连接建立的请求。当连接建立后,NIOAcceptor.accept方法会将连接绑定到一个NIOProcessor上,由NIOProcessor继续处理该连接上后续的读写请求。


可以看出,对于服务端口来说,NIOAcceptor只有一个,NIOProcessor的数目则一般和CPU核数保持一致。


3)MPP Server的启动


CN作为MPP集群中的一个,还需要启动端口来进行CN之间的通信。


startMppServer会进行MPP服务的启动。  


4)CDC服务的启动


CobarServer.tryStartCdcManager会进行CDC的启动。


7:结语


至此,CN就启动完成了。这个过程包含了CN中绝大多数组件,鉴于篇幅原因,没有完整介绍每个组件的作用。如果你对这些组件中的哪一个感兴趣,欢迎留言给我们,我们会在后续的文章中,对一些关键的组件做进一步详细的介绍。  

相关文章
|
2月前
|
SQL 关系型数据库 MySQL
开源新发布|PolarDB-X v2.4.2开源生态适配升级
PolarDB-X v2.4.2开源发布,重点完善生态能力:新增客户端驱动、开源polardbx-proxy组件,支持读写分离与高可用;强化DDL变更、扩缩容等运维能力,并兼容MySQL主备复制及MCP AI生态。
开源新发布|PolarDB-X v2.4.2开源生态适配升级
|
2月前
|
SQL 关系型数据库 MySQL
开源新发布|PolarDB-X v2.4.2开源生态适配升级
PolarDB-X v2.4.2发布,新增开源Proxy组件与客户端驱动,支持读写分离、无感高可用切换及DDL在线变更,兼容MySQL生态,提升千亿级大表运维稳定性。
660 24
开源新发布|PolarDB-X v2.4.2开源生态适配升级
|
7月前
|
关系型数据库 MySQL 数据库
MyEMS开源系统安装之数据库
本文详细讲解MyEMS的安装步骤,重点介绍数据库架构与脚本部署。MyEMS支持MySQL 8.0、MariaDB 10.5及SingleStore 7.0等数据库服务器。通过命令行或客户端工具执行SQL脚本完成安装,包括多个数据库(如myems_billing_db、myems_energy_db等)。此外,提供解决常见问题的方法,如“用户拒绝访问”、“COLLATE设置”和“MAX_ALLOWED_PACKET错误”。注意,不建议在生产环境中将数据库安装于Docker容器内。
218 1
|
4月前
|
人工智能 关系型数据库 MySQL
开源PolarDB-X:单节点误删除binlog恢复
本文由邵亚鹏撰写,分享了在使用开源PolarDB-X过程中,因误删binlog导致数据库服务无法启动的问题及恢复过程。作者结合实践经验,详细介绍了在无备份情况下如何通过单节点恢复机制重启数据库,并提出了避免类似问题的几点建议,包括采用高可用部署、定期备份及升级至最新版本等。
|
7月前
|
存储 Cloud Native 关系型数据库
PolarDB开源:云原生数据库的架构革命
本文围绕开源核心价值、社区运营实践和技术演进路线展开。首先解读存算分离架构的三大突破,包括基于RDMA的分布式存储、计算节点扩展及存储池扩容机制,并强调与MySQL的高兼容性。其次分享阿里巴巴开源治理模式,涵盖技术决策、版本发布和贡献者成长体系,同时展示企业应用案例。最后展望技术路线图,如3.0版本的多写多读架构、智能调优引擎等特性,以及开发者生态建设举措,推荐使用PolarDB-Operator实现高效部署。
410 4
|
存储 关系型数据库 MySQL
开源PolarDB- X|替换Opengemini时序数据场景下产品力校验
本文作者:黄周霖,数据库技术专家,就职于南京北路智控股份有限公司,负责数据库运维及大数据开发。
|
7月前
|
SQL 关系型数据库 分布式数据库
PolarDB开源数据库入门教程
PolarDB是阿里云推出的云原生数据库,基于PostgreSQL、MySQL和Oracle引擎构建,具备高性能、高扩展性和高可用性。其开源版采用计算与存储分离架构,支持快速弹性扩展和100%兼容PostgreSQL/MySQL。本文介绍了PolarDB的安装方法(Docker部署或源码编译)、基本使用(连接数据库、创建表等)及高级特性(计算节点扩展、存储自动扩容、并行查询等)。同时提供了性能优化建议和监控维护方法,帮助用户在生产环境中高效使用PolarDB。
2372 21
|
3月前
|
缓存 关系型数据库 BI
使用MYSQL Report分析数据库性能(下)
使用MYSQL Report分析数据库性能
160 3
|
3月前
|
关系型数据库 MySQL 数据库
自建数据库如何迁移至RDS MySQL实例
数据库迁移是一项复杂且耗时的工程,需考虑数据安全、完整性及业务中断影响。使用阿里云数据传输服务DTS,可快速、平滑完成迁移任务,将应用停机时间降至分钟级。您还可通过全量备份自建数据库并恢复至RDS MySQL实例,实现间接迁移上云。
|
3月前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS费用价格:MySQL、SQL Server、PostgreSQL和MariaDB引擎收费标准
阿里云RDS数据库支持MySQL、SQL Server、PostgreSQL、MariaDB,多种引擎优惠上线!MySQL倚天版88元/年,SQL Server 2核4G仅299元/年,PostgreSQL 227元/年起。高可用、可弹性伸缩,安全稳定。详情见官网活动页。
783 152

相关产品

  • 云原生数据库 PolarDB