后端DevOps云原生微服务【免费下载链接】spinnakerSpinnaker is an open source, multi-cloud continuous delivery platform for releasing software changes with high velocity and confidence.项目地址https://gitcode.com/gh_mirrors/sp/spinnaker点击查看免费下载本文以 Spinnaker 编排引擎 orca 的orca-peering模块orca/orca-peering/README.md为核心系统讲解多个 orca 集群各自持有独立数据库之间如何同步执行execution数据覆盖peer/partition/foreign execution三大核心概念、基于PeeringAgent的增量复制算法、完整的orca.ymlpeering profile 配置与参数调优以及配套的监控指标、动态开关和orca-interlink远程操作能力。读完本文你将能够为多区域 Spinnaker 部署或数据库迁移场景配置并运维一套可用的 orca 执行数据对等peering机制。背景与问题为什么 orca 需要 Peering在标准拓扑中单个 orca 集群对应一个独立的 [SQL] 数据库该数据库既保存全部执行历史execution history也保存执行队列execution queue。一旦出现以下两类场景问题就随之而来多区域multi-region部署不同区域各有一个 orca 集群和各自的数据库用户期望某个区域的执行记录在其他区域也能被看到、被查询甚至被远程操作。数据库迁移database migration把 orca 从旧数据库迁往新数据库的过渡期新旧两套数据库需要保持执行数据一致。orca-peering正是为了解决多个 orca 安装每个都带自己的数据库之间相互通告变更这一半实验性semi-experimental问题而生的模块。它是一个轮询式的数据同步代理从 peer 数据库中把执行数据复制到本地数据库并保证复制过来的数据以只读方式存在避免两个集群对同一执行互相操作造成冲突。核心概念peer、partition 与 foreign execution理解 peering 机制前必须先建立三个概念peer对等集群一个我们从中复制数据的 orca 集群其数据库可以是只读副本。每个 orca 集群拥有一个 ID例如us-east-1、us-west-2。在 yaml 配置中peer 由数据库连接 ID两者共同定义。典型场景下ID 为us-west-2的 orca 集群可以与 ID 为us-east-1的集群互相对等反之亦然。partition分区数据库中的执行记录都带有 partition 标记partition 与上述 peer ID 同义。当一条执行从 ID 为us-east-1的 peer 被peered复制过来时它会被以partition us-east-1的方式持久化到本地数据库。由于历史原因早期执行记录可能没有 partition 字段因此一个 orca 集群会把partition NULL或partition 本集群 ID的执行视为自己所有。这一点在源码中同样成立——MySqlRawAccess.kt 在查询执行 ID 时partition 约束就是partition IS NULL或partition 指定值两种分支。foreign execution外部执行出现在本地数据库中、但 partition 被标记为某个 peer 的执行。这些执行本质上是只读的当前 orca 集群无法对它们执行任何变更操作。源码中复制时会强制把每条执行的 partition 字段改写为 peer ID见下文 ExecutionCopier 的分析从而保证属于谁的判定一致。Peering 机制能做什么从 README 的定义看peering 机制完成三件事同步复制执行数据把 pipelines 和 orchestrations 两类执行从 peer 的数据库复制到本地集群数据库允许对 foreign execution 执行操作例如操作正在 peer 上运行的执行依托orca-interlink模块通过消息转发给实际拥有者执行尚未实现接管执行所有权取得之前由 peer 操作的执行并继续运行此能力在 README 中标注为 still to come。执行同步Execution Peering的原理执行同步本质上就是把执行从一份数据库复制到另一份数据库但有一个关键取舍执行历史需要被 peered执行队列则不能。为什么队列不能复制因为队列被复制会导致同一执行在多个集群被重复调度duplicate executions队列的变更频率和带宽极高复制它会为数据库带来难以承受的开销。因此 peering 只针对执行数据本身及其 stages而队列维持在各集群本地。所有 peering 逻辑都位于 PeeringAgent.kt算法细节见其代码注释高层思路如下给定一个 peer ID 及其数据库连接可指向只读副本将所有带该 peer ID 的 foreign execution 镜像到本地数据库复制过程中所有执行被标注为来自该 peer写入partition列任何对 foreign execution即partition ! 本集群 ID的执行的操作尝试都会失败。PeeringAgent 的单轮执行流程从源码看PeeringAgent继承自AbstractPollingNotificationAgent每个轮询周期由intervalMs控制执行一次tick()。tick()的流程PeeringAgent.kt为先通过DynamicConfigService检查全局开关pollers.peering与针对本 peer 的开关pollers.peering.PEERID两者均默认开启依次对PIPELINE与ORCHESTRATION两种执行类型执行复制传播删除操作peerDeletedExecutions若配置了自定义 peerer调用invokeCustomPeerer()整个过程被pollers.peering.lag计时器包裹用于度量单轮总耗时。对每种执行类型复制又分为两个阶段PeeringAgent.kt首轮运行isFirstRun只复制已完成的执行completed。原因很直接首次批量复制可能要耗时 20 分钟以上此时复制进行中的执行会立刻过时没有意义。后续运行先做已完成执行的增量复制再复制活动中的执行active。进行中执行的数量少、变化快因此每轮全量抓取当前活动执行 ID 并复制。peerCompletedExecutions内部通过doMigrate完成增量差量计算PeeringAgent.kt算法要点从源库取回updated_at大于游标updatedAfter的已完成执行 ID同时覆盖partition peeredId与partition NULL两批从本地库取回已被复制的对应执行 ID需要复制的 源库有、且updated_at比本地更新的执行需要删除的 本地有、但源库已不存在的执行删除前校验maxAllowedDeleteCount阈值超过则整轮不做删除并记错误指标防止误删全部执行复制完成后把最新 updated_at − clockDriftMs作为新的游标从而容忍集群间时钟漂移。删除的传播peerDeletedExecutionsPeeringAgent.kt依赖deleted_executions表该表的主键是自增 intPeeringAgent用它作为游标记录已传播的删除位置只有整批删除全部成功后游标才会推进失败则下轮重试。对不存在的执行执行删除是无害的只是浪费少量数据库 CPU。并行复制与分块细节ExecutionCopier实际的批量复制由 ExecutionCopier.kt 完成copyInParallel把待复制 ID 按chunkSize分块放入并发队列起min(threadCount, 分块数)个工作线程并行消费ExecutionCopier.kt单个分块的复制顺序非常讲究ExecutionCopier.kt先抓执行行、再抓 stage 行——因为差量计算以执行的updated_at为准绝不能出现stage 抓完、执行又被更新的时序颠倒stage 比执行新没问题下一轮 agent 运行会自行修正先复制 stages、再复制 executions——若先保存执行用户可能看到一条还没有任何 stage 的执行源库 stage 列表可能已变化例如重启 deploy stage 会删除其合成 stages 重新开始因此先把本地源已不存在的 stage删掉再对剩下的做增量更新/复制复制执行行时强制把partition字段改写为peeredId然后通过loadRecords基于INSERT ... ON DUPLICATE KEY UPDATE写入本地。测试用例 PeeringAgentSpec.groovy 对上述逻辑做了行为验证包括全局/单 peer 动态开关是否生效、已完成执行的差量计算是否正确含删除集合、待复制集合、游标推进其中clockDrift在测试中被设为 10ms 以验证时钟漂移对游标的影响。配置实战orca.yml 中的 peering profileREADME 给出了一个可直接参考的peeringprofile 配置片段位于orca.yml完整保留如下spring: profiles: peering pollers: peering: enabled: true poolName: foreign id: us-west-2 intervalMs: 5000 # This is the default value threadCount: 30 # This is the default value chunkSize: 100 # This is the default value clockDriftMs: 5000 # This is the default value queue: redis: enabled: false keiko: queue: enabled: false sql: enabled: true foreignBaseUrl: URL_OF_MYSQL_DB_TO_PEER_FROM:3306 partitionName: LOCAL_PARTITION_NAME connectionPools: foreign: jdbcUrl: jdbc:mysql://${sql.foreignBaseUrl}/orca?ADD_YOUR_PREFFERED_CONNECTION_STRING_PARAMS_HERE user: orca_service password: ${sql.passwords.orca_service} connectionTimeoutMs: 5000 validationTimeoutMs: 5000 maxPoolSize: ${pollers.peering.threadCount}这份配置同时传达了几个关键设计开启 peering 的同时必须关闭队列复制相关组件queue.redis.enabled、keiko.queue.enabled均为false与队列不复制的原则一致sql.connectionPools.foreign定义了指向 peer 数据库的连接池maxPoolSize直接取自pollers.peering.threadCount保证并行复制线程数有足够的连接可用源码 PeeringAgentConfiguration.kt 以ConditionalOnExpression(${pollers.peering.enabled:false})条件装配整个 peering 代理即默认关闭、只有显式开启该 profile 时才注册PeeringAgentBean同时它要求peerIdpeer 的 ID与poolName两个参数必须指定否则直接抛出ConfigurationException。补充说明在源码的配置属性类 PeeringAgentConfigurationProperties.kt 中该peer ID字段被声明为peerIdREADME 的配置键写作id两者的默认值依次对应intervalMs5000、threadCount30、chunkSize100、clockDriftMs5000、enabledfalse。参数说明表参数默认值说明pollers.peering.enabledfalse用于开启或关闭 peeringpollers.peering.poolName[REQUIRED]访问 foreign 数据库所使用的连接池名称对应上文sql.connectionPools.foreignpollers.peering.id[REQUIRED]peer 的 ID每个数据库必须唯一pollers.peering.intervalMs5000执行迁移的间隔每一轮执行一次增量复制。间隔越短延迟越低但 CPU 与数据库负载越高pollers.peering.threadCount30用于批量迁移的线程数。大数值只在最初的批量导入阶段有明显帮助此后增量通常很小超过 2 基本没有区别pollers.peering.chunkSize100复制数据时的分块大小单次最多修改的行数pollers.peering.clockDriftMs5000允许操作同一数据库的多个 orca 实例之间存在这么大的时钟漂移pollers.peering.maxAllowedDeleteCount100单次最多删除的执行数。若删除量 Δ 超过该值则本轮不执行删除并累加错误指标。用于防止误删全部执行可通过DynamicConfigService动态调整三个关键参数的深入解读pollers.peering.intervalMs这是 peering agent 两次运行之间的间隔即上一轮 agent 运行结束到下一轮开始的时间。加上单轮运行本身的耗时共同决定了一条执行从一个数据库复制到另一个数据库的延迟。README 给出了一个参考基准在约有 600 万历史执行、任意时刻约 200 个活动执行的 MySQL orca 安装上单轮 agent 运行约耗时 8 秒。数值越小 peering 延迟越低但数据库负载越高。pollers.peering.clockDriftMs定义比较执行updated_at时间戳时的容差因子。由于时间戳由各实例而非数据库本身写入实例之间无法保证时钟完全同步。例如抓取源库快照时最新updated_at是 1000但另一个未完全同步的实例可能在快照之后又以时钟 998 修改了某条执行——如果没有容差这条变更可能被漏掉。源码中每轮完成后的游标会减去clockDriftMsPeeringAgent.kt正是这一容差的落地。pollers.peering.maxAllowedDeleteCount这是防止 peering agent 灾难性故障的安全阀——防止它错误地决定把本地数据库的全部执行删除。取值应大于常规操作中单次最大删除量但远小于库中执行总数README 建议的量级约为全部执行的 0.25%。该值既可作为静态配置也可通过DynamicConfigService在运行时调整源码中doMigrate每次都以pollers.peering.max-allowed-delete-count动态读取默认 100删除量超出即跳过删除并累加错误指标PeeringAgent.kt。数据库访问层MySqlRawAccess 的实现细节SqlRawAccess是 peering 与数据库交互的抽象层SqlRawAccess.kt定义了getCompletedExecutionIds、getActiveExecutionIds、getDeletedExecutions、getStageIdsForExecutions、getExecutions、getStages、deleteStages、deleteExecutions、loadRecords等操作。当前唯一的实现是 MySqlRawAccess.kt其中值得注意的工程细节初始化时查询数据库max_allowed_packet并预留 8192 字节语句开销用于在批量写入时按包大小自动拆分MySqlRawAccess.kt执行 ID 查询带 partition 约束NULL或指定值见上文删除时由于 stages 表索引多、删除代价高单次删除分块取min(chunkSize, 5)进一步收紧MySqlRawAccess.kt对已完成执行 ID 查询这类读操作做了 3 次、间隔 500ms 的重试封装withRetryMySqlRawAccess.kt表名映射集中在 Utils.ktpipeline 对应pipelines/pipeline_stagesorchestration 对应orchestrations/orchestration_stages。自定义扩展CustomPeerer如果内置的执行 stages复制不足以覆盖你的数据同步需求可以实现 CustomPeerer.kt 接口并以 Spring Bean 暴露init(srcDb, destDb, peerId)让自定义 peerer 完成初始化可通过srcDb.runQuery拿到 jooq 上下文对源库执行查询doPeer()在每一轮默认 peering 动作全部完成后被调用返回true表示成功、false表示失败。PeeringAgent初始化时会先调用init并捕获异常失败则该自定义 peerer 不会被启用同时累加pollers.peering.customPeerer.numErrors指标每个周期最后执行doPeerPeeringAgent.kt。对 foreign execution 执行操作orca-interlinkREADME 明确列出了用户可以通过 UI/API 对一条执行发起的操作orca 会基于这些操作变更执行状态cancel取消一条执行pause暂停一条执行resume恢复一条执行pass judgement对一条执行进行判定delete删除一条执行这些操作必须发生在拥有该执行的集群/实例上。当本地集群面对一条 foreign execution 时不能直接操作而是通过orca-interlink模块把意图转达给实际拥有者。从仓库源码看orca/orca-interlink 模块提供了对应的消息事件类型CancelInterlinkEvent、DeleteInterlinkEvent、PauseInterlinkEvent、ResumeInterlinkEvent、PatchStageInterlinkEvent、RestartStageInterlinkEvent统一继承InterlinkEvent并带有Interlink消息发送抽象与 AWS 实现InterlinkAmazonMessageHandler使用 SQS 等云消息服务承载跨区域通信的推断来自该实现类的命名与包结构。同时InterlinkConfigurationProperties.java 暴露了interlink.flagger相关配置enabledtrue、maxSize32、threshold8、lookbackSeconds60用于对消息做标记/限流控制。README 在该节标注 TBD说明远程操作部分仍在演进中。监控Emitted Metrics 与推荐告警peering agent 通过 PeeringMetrics.kt 发射如下指标均带有peerId标签部分带有executionType/state标签可用于监控 peering 系统的健康状况指标说明pollers.peering.lagTimer秒度量执行单轮迁移循环的耗时该值 agent 的intervalMs即为有效延迟。应是一个相当平稳的数值pollers.peering.numPeeredCounter已复制执行的数量应保持平稳——即与活动执行数量大致相当pollers.peering.numDeletedCounter已删除执行的数量pollers.peering.numStagesDeletedCounter复制过程中删除的 stage 数量纯信息性指标pollers.peering.numErrorsCounter执行复制过程中遇到的错误数应对其设置告警源码中除上述外还发射pollers.peering.customPeerer.numErrors自定义 peerer 的错误计数并且lag同时记录单种执行类型PIPELINE/ORCHESTRATION与整体OVER_ALL两种维度PeeringMetrics.kt。如果使用了 peering 功能README 建议为以下指标配置告警pollers.peering.numErrors 0pollers.peering.numPeered 0持续一段时间取决于你的活动执行稳态规模pollers.peering.lag 60持续一段时间约 3 分钟运行时动态控制Dynamic properties以下动态属性可通过DynamicConfigService在运行时控制无需重启集群属性默认值说明pollers.peering.enabledtrue设为false时关闭全部 peeringpollers.peering.PEERID.enabledtrue设为false时关闭指定 peer ID 的全部 peeringpollers.peering.max-allowed-delete-count100单轮 agent 运行允许删除的最大执行数这三项开关在PeeringAgent.tick()中逐轮生效前两项经dynamicConfigService.isEnabled(...)判断默认true见 PeeringAgent.kt删除阈值则每次动态读取见 PeeringAgent.kt。测试 PeeringAgentSpec.groovy 专门验证了全局禁用时不触发任何查询、单 peer 禁用时不触发该 peer 查询的动态开关行为。Caveats使用前提与注意事项仅支持 MySQL目前 peering 只支持 MySQL。要扩展到其他数据库引擎只需为对应引擎实现一个新的SqlRawAccess参见 SqlRawAccess.kt装配逻辑中PeeringAgentConfiguration目前也仅在 jooq dialect 为MYSQL时构建MySqlRawAccess否则抛出UnsupportedOperationExceptionPeeringAgentConfiguration.kt。建议只用一个实例运行 peering agent/profile目前还没有跨实例锁cross instance locking多个实例同时跑 peering 可能造成重复复制或竞争。该限制未来有望改进。值得说明的是源码层面PeeringAgent继承自AbstractPollingNotificationAgent并接收NotificationClusterLock锁基础设施已接入但 README 明确提示当前阶段仍以单实例运行为准。尚未实现的能力README 明确标注了两个待办方向属演进中的规划而非当前可用能力接管执行所有权Taking ownership从 peer 手中取得某条执行的所有权并继续运行即failover/接管能力对 foreign execution 执行操作README 的 TBD 说明该能力仍在开发中需要与orca-interlink的远程消息通道协同落地。从代码结构看orca-peering模块目前的稳定能力集中在执行数据的单向镜像 删除传播 监控与动态开关多区域场景下的完整读写闭环仍需与orca-interlink一起演进。赞分享后端DevOps云原生微服务【免费下载链接】spinnakerSpinnaker is an open source, multi-cloud continuous delivery platform for releasing software changes with high velocity and confidence.项目地址https://gitcode.com/gh_mirrors/sp/spinnaker点击查看免费下载相关推荐Atlas跨国数据库部署终极指南实现多区域数据同步与零停机迁移Atlas跨国数据库部署终极指南实现多区域数据同步与零停机迁移 在全球化的今天企业需要将数据库部署到多个地理区域以满足本地化需求和法规要求。Atlas作为现数据库开发工具数据工程Resque跨集群数据同步多区域部署的数据一致性Resque跨集群数据同步多区域部署的数据一致性 你是否在多区域部署Resque时遇到过队列数据不同步、任务执行状态混乱的问题本文将从实际场景出发详解如何任务调度消息队列后端INFINI Console数据迁移跨集群数据同步与复制INFINI Console数据迁移跨集群数据同步与复制 概述 在分布式搜索架构中数据迁移和跨集群复制是运维团队面临的核心挑战。INFINI Console后端数据库可观测性告警运维上一篇5分钟搞定Notion免费版PDF导出告别复制粘贴的高效工具下一篇高效PDF文献翻译工具Zotero PDF Translate功能解析与实用指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
企业数字化 ERP 产品动态
相关推荐
easy-vibe 后端基础:消息队列(Message Queue)与事件驱动架构实战指南 教程文档 【免费下载链接】easy-vibe 从 0 到 1 学会 vibe coding,项目制学习 项目地址: https://gitcode.com/datawhalechina/easy-vibe 点击查看 免费下载 导读
消息队列(Message Queue, MQ)是分布式系统解耦、削峰与保障可靠… · 2026/9/25 3:17:50
WorkBuddy 工作流实战:从安装到跑通本地文件批量处理 1. 为什么我要花时间折腾 WorkBuddy 这套工作流第一次听说 WorkBuddy 是在一个做企业数字化的朋友群里,有人丢了一张截图,说他们团队把简历筛选、日报汇总、周报生成这三件事全部塞进了一个桌面工作台里,每天早上打开电脑,AI 已经… · 2026/9/25 3:17:43
CodeCombat 开源项目完全指南:多人在线编程游戏的技术架构、本地开发与贡献实践 游戏开发教育前端后端 【免费下载链接】codecombat Game for learning how to code. 项目地址: https://gitcode.com/gh_mirrors/co/codecombat 点击查看 免费下载 CodeCombat 是一个以"游戏化编程学习"为核心的多人在线编程游戏开源项目——玩家通过编写… · 2026/9/25 3:52:32
Altium Designer交互式BOM插件开发:从原理图采集到PCB高亮回跳 简介:Altium Designer 用户常需在原理图与 PCB 设计流程中维护物料清单,但软件原生并不直接提供交互式 BOM 导出能力。这款插件正是针对这一缺口设计的效率工具,面向需要将 BOM 以网页化、可交互形式交付的硬件工程师与采购人员。压缩包共 35… · 2026/9/25 3:52:32
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37