ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Nacos 持久化与 Dump 机制深度解析:嵌入式/外部存储、CP 写入链路与本地服务缓存重建

Nacos 持久化与 Dump 机制深度解析:嵌入式/外部存储、CP 写入链路与本地服务缓存重建 Nacos 持久化与 Dump 机制深度解析嵌入式/外部存储、CP 写入链路与本地服务缓存重建【免费下载链接】nacosan easy-to-use dynamic service discovery, configuration and service management platform for building AI cloud native applications.项目地址: https://gitcode.com/GitHub_Trending/na/nacos导读本文以 Nacos 官方《Persistence And Dump Spec》为骨架系统拆解 Nacos 的持久化与 Dump 基础能力——包括嵌入式Derby与外部Hikari JDBC两类存储模式的选择规则、DataSourceService数据源契约、分布式嵌入式存储的 CP 写路径、Config 领域的 Dump 与本地服务缓存重建机制以及维护清理与边界规则。读完本文你将能理解 Nacos 服务端数据持久化在哪、如何被写入、如何重建本地读缓存的完整链路并能对照 persistence 模块源码与 config 模块实现定位每一层职责。1. 定位持久化与 Dump 是基础能力不是领域资源在 Nacos 的架构分层中持久化Persistence与 Dump 属于Foundation基础能力而非 Config、Naming、AI 等领域的业务资源。它们提供持久化存储的选择与生命周期管理JDBC 数据源的初始化、健康检查与事务访问持久化层的交互抽象数据库操作、行映射、事务与 Repository 支持嵌入式存储启用时的 CP 复制面向高频读的本地 Dump 文件与 JVM 服务缓存从持久化状态重建本地服务状态的启动与修复流程。而领域规格Domain Spec则负责逻辑 Schema、资源身份、校验、鉴权与用户可见行为。持久化基础能力只负责存储管道storage plumbing严禁重新定义 Config、Naming、AI 或 Auth 资源的语义。由于持久化的数据通常是领域语义数据因此具体的 Repository 接口与实现可能位于领域模块而非persistence模块中。最典型的例子是 Config 领域的ConfigInfoPersistService它的嵌入式与外部实现之所以放在 config 模块是因为这些操作理解 Config 记录、历史、灰度字段、容量元数据与 Config 可见性规则——这些语义不属于通用持久化层。2. 存储模式Storage ModesNacos 支持两大类存储模式模式当前实现持久化事实来源Source of Durable Truth嵌入式存储通过LocalDataSourceServiceImpl使用 Derby集群模式下写入经 CP 协议排序单机 Derby或nacos_configCP 组 本地 Derby 状态机外部存储通过ExternalDataSourceServiceImpl使用 Hikari 托管的 JDBC 数据源由数据源属性与方言规则选定的外部数据库选择规则与 DatasourceConfiguration 的实现一一对应单机模式默认使用嵌入式存储集群模式默认使用外部存储配置了非空且非derby的数据源平台时选择外部存储集群模式可通过嵌入式存储属性开启嵌入式分布式存储一旦选定DynamicDataSource必须返回匹配的DataSourceService且每个进程只初始化一次。在源码中DynamicDataSource.java 使用单例模式通过DatasourceConfiguration.isEmbeddedStorage()判断后懒加载并缓存LocalDataSourceServiceImpl或ExternalDataSourceServiceImpl。而 DatasourceConfiguration 的加载逻辑可以概括为platform 解析数据源方言平台如 mysql useExternalDb platform 非空 且 platform ! derby 若 useExternalDb关闭嵌入式存储 否则embeddedStorage 单机模式标志 或 系统属性 embeddedStoragetrue 若仍未开启嵌入式自动升级为外部存储关键点存储模式是运维部署选择。领域规格不得因为持久化存储模式变化而暴露不同的资源身份。2.1 配置层面的落点外部存储的典型配置位于 distribution/conf/application.properties# 启动时选择的数据库方言遗留的 spring.sql.init.platform 仍被支持 #nacos.plugin.datasource-dialect.typemysql #spring.sql.init.platformmysql # DB 数量 # nacos.plugin.datasource.db.num1 # DB 连接 URL # nacos.plugin.datasource.db.url.0jdbc:mysql://127.0.0.1:3306/nacos?characterEncodingutf8connectTimeout1000socketTimeout3000autoReconnecttrueuseUnicodetrueuseSSLfalseserverTimezoneUTC # nacos.plugin.datasource.db.usernacos # nacos.plugin.datasource.db.passwordnacos # JDBC 查询超时秒 # nacos.plugin.datasource.db.query-timeout3注意遗留的db.*属性与QUERYTIMEOUTJVM 属性仍作为别名受支持当两种形式同时配置时nacos.plugin.datasource.db.*优先。3. 数据源契约Datasource ContractDataSourceService是存储运行时契约。从 DataSourceService.java 的接口定义看它提供JdbcTemplate getJdbcTemplate()SQL 执行入口TransactionTemplate getTransactionTemplate()事务写入入口String getDataSourceType()数据源类型与当前 JDBC URL用于诊断void init()/void reload()初始化与重载boolean checkMasterWritable()外部存储的主库可写检查。3.1 外部存储规则ExternalDataSourceServiceImpl见 ExternalDataSourceServiceImpl.java的实现要点数据源属性构建一个或多个 Hikari 数据源连接建立前会通过ConnectionCheckUtil.checkDataSourceConnection校验连通性存在多数据源时SelectMasterTask每 10 秒执行使用写探测选择主库对每个数据源执行DELETE FROM config_info WHERE data_idcom.alibaba.nacos.testMasterDB成功后即切换当前活跃的JdbcTemplate与事务管理器每个数据源周期性健康检查CheckDbHealthTask每 10 秒执行SELECT * FROM config_info_gray WHERE id 1探测失败则标记isHealthList为 false 并递增DatasourceMetrics.getDbException()外部存储健康状态可以是UP / WARN / DOWN取决于主库与从库的可用性reload()会先构建新池并完成探测再关闭旧池并摘除旧模板保证重载过程安全checkMasterWritable()通过SELECT read_only1 秒超时判断主库是否可写防止主库不可用时登录接口长时间阻塞额外提供 PostgreSQL 租户 Schema 校验validatePostgresqlTenantSchema检查config_info等表的tenant_id列必须为NOT NULL DEFAULT 否则提示应用META-INF/pg-upgrade-null-tenant-id.sql迁移脚本。3.2 嵌入式存储规则LocalDataSourceServiceImpl见 LocalDataSourceServiceImpl.java本地 Derby 从META-INF/derby-schema.sql或{nacos.home}/conf/derby-schema.sql初始化JDBC URL 形如jdbc:derby:{nacos.home}/data/derby-data;createtrue单机嵌入式存储直接对本地 Derby 执行分布式嵌入式存储启动时会清空并重新打开本地 DerbycleanAndReopenDerby先jdbc:derby:;shutdowntrue关闭再删除derby-data目录重建因为有效状态必须来自 CP 日志回放与快照恢复Derby 健康状态在嵌入式 CP 状态机上报不可恢复的 apply 错误时置为DOWN通过setHealthStatus与RaftDbErrorEvent事件联动嵌入式 JdbcTemplate 默认setMaxRows(50000)、setQueryTimeout(5000)毫秒级配置事务模板超时同为 5000。3.3 数据源方言插件数据源方言插件位于 Repository 之下、物理数据库家族之上详见 Datasource Dialect Plugin Spec。它们可以适配某类数据库平台的 SQL、Mapper、分页、生成主键与函数行为但不得改变逻辑数据含义、Schema 归属、鉴权与资源身份。方言选择属性为nacos.plugin.datasource-dialect.type遗留属性spring.sql.init.platform已标记Deprecated并计划在 Nacos 4.0.0 移除见 PersistenceConstant.java。4. Repository 契约Repository 服务在数据源细节之上定义领域存储语义是领域语义与持久化层抽象交汇的边界。核心规则摘录自规格原文并对照源码persistence模块可提供通用原语例如数据库操作、行映射注册RowMapperManager、存储常量PersistenceConstant与异步执行PersistenceExecutor当存储数据具有领域含义时领域模块可定义具体 Repository 接口与实现例如 Config 的ConfigInfoPersistServiceRepository 接口拥有逻辑操作新增、更新、删除、查询、历史、容量、元数据持久化Repository 实现可在嵌入式与外部存储间不同但必须保持相同的领域语义Repository 实现可使用数据源方言 Mapper 构建数据库特定 SQL但校验、资源身份、历史、Trace 与鉴权语义必须保留在领域 Repository 层Controller、请求处理器与领域服务应依赖领域 Repository 接口而非直接调用 Mapper 或方言 SPI用户可见的领域写入必须在同一领域操作中记录规格要求的历史、Trace、容量与变更元数据大范围列表与搜索操作必须分页或有界源码中 JdbcTemplate 默认setMaxRows(50000)即为防止内存膨胀的兜底Repository 代码不得直接使用来自公共 API 输入的裸 SQL 片段必须经校验与方言受控构造方言插件与 Mapper不得成为定义领域行为或兼容性策略的替代场所仅为兼容保留的 Schema 字段不得成为新的语义契约除非领域规格明确提升其地位。Config 的 Repository 接口定义见 Config Persistence, Dump, And History Spec。5. 分布式嵌入式存储CP 写入链路分布式嵌入式存储借助 CP 基础能力保证持久化写入排序当前 Config 嵌入式存储组为nacos_config常量CONFIG_MODEL_RAFT_GROUP见 PersistenceConstant.java。5.1 写入模型规格给出的完整写入链路Repository operation - ModifyRequest list - DatabaseOperate.update / blockUpdate - CP WriteRequest(group nacos_config) - JRaft commit - DistributedDatabaseOperateImpl.onApply - local Derby transaction - embedded apply hooks对照源码 DistributedDatabaseOperateImpl.java该类通过Conditional(ConditionDistributedEmbedStorage.class)启用继承RequestProcessor4CP并实现BaseDatabaseOperate。其类注释中给出了一张完整的时序图PersistService.publishConfig→ 保存 SQL 到SqlContextUtils上下文 →DatabaseOperate提交ListModifyRequest→JRaftProtocol→onApply落库 Apache Derby → 返回执行结果给JdbcTemplate。ModifyRequest.java 是携带executeNo执行序号、sql、args与rollBackOnUpdateFail标志的可序列化写请求DatabaseOperate.java 接口提供queryOne/queryMany读、update/blockUpdate写与dataImport外部数据源导入嵌入式三类操作其中blockUpdate()会取出当前线程EmbeddedStorageContextHolder中的 SQL 上下文执行并自动清理。5.2 关键规则分布式嵌入式写入必须先经 CP commit本地 Derby apply 之后才被视为持久化需要排序时ModifyRequest按executeNo排序后执行必须确定性SQL 限制器SqlLimiter/SqlTypeLimiter必须在执行前拒绝不支持的查询或修改形式apply 钩子EmbeddedApplyHook必须在已提交的 apply 之后运行且不得用慢操作阻塞状态机BadSqlGrammarException与DataIntegrityViolationException作为操作失败返回而不是停止 Raft 状态机严重的数据源访问失败可能表现为一致性错误且必须更新可观测的存储健康状态。5.3 分布式读取安全分布式嵌入式存储激活时读走 CP 读路径。启动 dump 可设置阻塞读上下文常量EXTEND_NEED_READ_UNTIL_HAVE_DATA 00--0-read-join-0--00让节点在存在可读数据之前等待再重建服务缓存。分布式嵌入式读请求在 JDBC 执行前必须校验声明的结果目标类型Mapper 查询只能使用已注册到持久化行映射注册表RowMapperManager的 row mapper 类名标量查询只能使用显式白名单的基础结果类型。源码中BASIC_RESULT_TYPES仅允许Integer、Long、String三类见 DistributedDatabaseOperateImpl.java从固定类常量解析不采用请求驱动的类加载缺失、未知或与查询类型不兼容的目标类型必须使读请求失败——这是防止嵌入式读路径被恶意或错误类型利用的关键安全设计。快照规则由 CP Consistency Spec 定义。嵌入式存储必须提供足够的快照数据以便重启或成员变更后重建本地 Derby 状态。6. Dump 与本地服务缓存Dump 是本地服务状态的重建与刷新机制不是第二个持久化事实来源。持久化层始终是持久化事实来源。6.1 Config Dump 模型Durable write or cluster change notification - ConfigDataChangeEvent or ConfigChangeClusterSyncRequest - DumpRequest - DumpTask keyed by groupKey or groupKey gray grayName - repository reload - ConfigDumpEvent - ConfigCacheService - local disk dump and JVM cache - LocalDataChangeEvent - listener/watch push这条链路在 config 模块中有完整实现DumpService负责调度DumpTask以groupKey或groupKey gray grayName作为任务键ConfigCacheService负责把最新内容写入本地磁盘与 JVM 缓存随后发布LocalDataChangeEvent触发监听器/长轮询推送。6.2 启动 Dump 规则启动时先清理旧的正式与灰度 dump 文件再从持久化重建本地 dump 数据启动时把正式与灰度记录 dump 到本地磁盘与 JVM 缓存嵌入式集群启动必须等待 CP 组具备可读数据后启动 dump 才算完成对应上文阻塞读上下文外部存储启动可直接从配置的数据源 dump启动 dump 失败 服务启动的致命失败。6.3 运行时 Dump 规则一次成功的持久化写入后领域必须为该资源调度 dump 刷新集群变更通知可要求对端节点从持久化重新加载本地 dump但通知载荷不是权威内容全量 dump 任务是修复与漂移控制机制变更 dump 任务应按键组织使同一资源的重复变更可以按 Task Execution Spec 的规则合并或替换dump apply 只有在本地服务状态更新之后才能发布本地变更事件遵循 Event Dispatch And NotifyCenter Spec。对当前 Config 实现而言运行时客户端读全部由本地缓存与 dump 文件服务持久化层仍是持久化事实来源——这也是 Nacos 配置读取能做到毫秒级响应的核心设计。7. 本地 Dump 存储本地 dump 存储由ConfigDiskServiceFactory选择见 ConfigDiskServiceFactory.javarawdisk是默认的config_disk_type通过System.getProperty(config_disk_type, rawdisk)读取未知值也回退到 raw disk 行为rocksdb可被选择为替代的本地 dump 后端ConfigRocksDbDiskService本地 dump 存储必须实现save、remove、read、清空正式记录、清空灰度记录raw disk 存储把正式与灰度内容放在 Nacos home 数据目录下按带命名空间与无命名空间两类路径分离dump 存储键必须从经过校验与编码的 Config 身份字段派生更换本地 dump 后端不得改变Config 资源身份、md5 语义、鉴权与持久化事实来源。这里需要特别强调本地 dump 存储属于服务缓存路径的一部分它不是 Repository 契约也绝不能作为独立的持久化数据库使用。8. 缓存更新规则单调可见性本地服务缓存必须对每个资源键保持单调可见性monotonic visibility携带更旧lastModified时间戳的 dump 必须被忽略内容 md5 变化时dump 必须同时更新本地磁盘内容与 JVM 缓存 md5 状态md5 未变但时间戳更新时dump 可只更新时间戳而不重写内容避免无谓 IOremove dump 必须删除本地磁盘数据并移除 JVM 缓存状态灰度 dump 还必须在字段变化时更新灰度规则、加密数据键与灰度排序同一资源键的缓存与 dump 变更必须由本地读写锁保护LocalDataChangeEvent是本地可见性事件不得视为跨节点复制保证参见 Event Dispatch And NotifyCenter Spec。安全边界如果本地磁盘已满或无法安全存储正式 dump 内容服务必须将之视为致命状态因为运行时查询路径依赖本地服务状态。9. 维护与清理持久化与 dump 维护操作属于管理能力Administrative Capabilities并带有明确的归属约束历史清理只能在存储模式属主节点上执行嵌入式单机唯一节点嵌入式集群Config 存储组的 CP Leader外部存储按成员顺序选出的第一个 Nacos 成员本地缓存全量 dump 是修复操作不得替代正常的发布/删除路径Derby 导入与查询操作是维护者专属操作必须由显式运维设置与权限保护源码中对应DerbyImportEvent、DerbyLoadEvent及DatabaseOperate.dataImport(File)大型导入与 dump 操作必须分批且有界维护 API 必须报告失败不得把部分存储修复静默当作成功。10. 边界规则Boundary Rules规格最后用十条边界规则收束各层职责这也是理解整个持久化体系最凝练的总结持久化是持久化存储管道领域规格定义资源含义Dump 文件与 JVM 缓存是派生的服务状态除非领域规格另有说明嵌入式分布式存储的持久性来自CP commit 与快照恢复而非仅本地 Derby 写入外部存储的持久性来自配置的外部数据库而非 Nacos 集群复制数据源方言插件适配的是SQL而非领域语义本地事件、dump 任务与缓存更新是实现内部细节除非接口规格显式暴露不再代表领域语义的 Schema 兼容字段必须标注为兼容或待移除。11. 关联规格速查Foundation Capabilities SpecCP Consistency SpecAP Consistency SpecInternal RPC And Cluster Request SpecTask Execution SpecEvent Dispatch And NotifyCenter SpecConfig Persistence, Dump, And History SpecConfig Listener And Watch SpecDatasource Dialect Plugin SpecConfig Encryption Plugin Spec12. 总结一图读懂 Nacos 持久化分层把整篇规格浓缩为分层视角领域语义层Config/Naming/AI - Repository 接口与实现如 ConfigInfoPersistService 持久化抽象层persistence 模块 - DatabaseOperate / RowMapperManager / 存储常量 数据源运行时层DataSourceService - LocalDataSourceServiceImpl | ExternalDataSourceServiceImpl 方言适配层插件 - Datasource Dialect Plugin适配 SQL不改语义 物理存储层 - 本地 Derby嵌入式 | MySQL/PG/Oracle 等外部库 服务缓存层dump - 本地磁盘 dump 文件 JVM 缓存仅服务读非持久化事实理解这一分层后再去看 persistence 模块的datasource、repository包以及 config 模块的service/dump、service/ConfigCacheService你就能在源码中精确对应到存储模式选择 → 数据源契约 → CP 写入 → dump 重建 → 缓存单调更新这条完整链路。【免费下载链接】nacosan easy-to-use dynamic service discovery, configuration and service management platform for building AI cloud native applications.项目地址: https://gitcode.com/GitHub_Trending/na/nacos创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表