当前位置: 首页 > news >正文

调度器多副本,不引 ZooKeeper:DB CAS + slot 分片就够了

调度器一挂,全平台定时作业停摆,所以单副本变多副本是绕不过去的一步。而说到「调度器 HA」,多数人的第一反应是条件反射式的:上 ZooKeeper(或 etcd)选个主,leader 干活,follower 待命。

「我的数据空间」(datastudiohappy.cn)的作业调度器(cron 触发 + DAG 工作流编排)走了另一条路:一行 ZK 代码都没有,整个多副本方案只用两样东西——DB 乐观锁 CAS 保正确性,slot 分片提吞吐。这篇讲清楚它是怎么闭环的。

一、多副本到底要保证什么

先把「HA」拆成四条可验证的性质:

  1. 同一次触发,全局只发生一次——双跑轻则浪费资源,重则数据写重(「删旧分区再写入」的 ETL 并发跑两遍);
  2. 任一副本挂掉,任务不丢不僵——在跑的被别人接管收尾,宕机漏掉的触发按策略补;
  3. 扩缩容自动再均衡——加副本活儿自动摊过去,减副本活儿自动被捡走,不靠人肉改分片;
  4. 成员变化的过渡期,以上三条不破——「现在有几个副本」的视图短暂不一致时,系统不出错。

第 1 条和第 2 条天然有张力:要「不丢」就得允许接管,要「不双跑」就得防接管和原执行者撞车。怎么解这个张力,是所有方案的分水岭。

二、四条路线,一张表说完

路线典型代表主要代价
ZK/etcd 选主大量自研调度器新增重量级组件且它自己也要 HA;follower 纯热备不出力;脑裂仍要 fencing 补
分布式锁Redis/ZK 锁租期两难:短了一次 GC 停顿就双跑,长了故障后干等;多一个故障域
DB 悲观行锁Quartz 集群模式所有节点排队过同一把FOR UPDATE,触发频率一高锁竞争即瓶颈
DB 乐观锁 CASAirflow 多 scheduler无等待、无租期难题、依赖零新增;需要自己把每个动作设计成条件更新

先例值得注意:Airflow 的多 scheduler 完全靠元数据库协调,官方明确不引 Raft/Paxos;DolphinScheduler 的多 master 靠命令表去重 + slot 取模分片,注册中心甚至提供纯 JDBC 实现。真正在大规模生产里跑的调度器,协调层早有「往 DB 收敛」的传统,ZK 从来不是标配。

选 CAS 的理由说穿了很朴素:调度器的一切状态——作业定义、实例、任务——本来就在 MySQL 里,「谁在跑」的权威在 DB,「谁来跑」的裁决权放 DB 就是最短路径。依赖清单每多一项,可用性是乘法不是加法。并且选主保证的只是「谁干活」,CAS 直接保证「每件事只被干一次」——后者才是真正要的性质,粒度更细,还顺便让 N 个副本能同时干 N 件不同的事。

三、四个核心机制

触发去重:对「下次触发时间」做 CAS。cron 不放内存定时器(多副本天然 N 份、重启即丢),而是一张触发表 + 近端扫描:每个副本每几秒扫「即将到期」的行(走索引,代价与作业总量脱钩),抢占是一条带条件的更新:

UPDATE触发表SET下次触发时间=:按cron算的下一次WHEREid=:idAND下次触发时间=:本次看到的值;

影响行数为 1 即抢到本次触发,为 0 说明别的副本已把时间推进,直接跳过——不加锁、不等待,MySQL 的行级原子性就是裁判。宕机漏掉的触发顺便解决:扫描发现触发时刻已超过宽限期,按 misfire 策略补跑(默认只补最近一次),基线就是表里持久化的触发时间本身。

执行去重:状态机 CAS + outbox。触发之后任务经消息队列派发,而 MQ 是 at-least-once 的,消息可能重复——去重不指望 MQ,在消费端用同一招:

UPDATE任务表SET状态='执行中'WHEREid=:idAND状态='已派发';

消息重复来十次,十个消费者做同一条 CAS,只有一个翻转成功,其余静默丢弃。「认领」与「发消息」放在同一个 DB 事务里(transactional outbox 模式),杜绝「已认领但消息漏发」的孤儿任务。两层 CAS 各管一段:触发一次靠前者,投递至少一次但执行恰好一次靠后者。

僵尸接管:心跳租约 + reaper。每个在跑任务记「属主进程 + 租约到期时间」,属主活着就周期续租(25 秒一续、租约 90 秒,连续错过三次心跳才判死,长作业不会因「跑得久」被误杀);进程死了续租自然停止,任一存活副本上的常驻 reaper 扫「非终态 + 租约过期」的任务做收尾。两条纪律直接融在这条路径里:收尾的副作用(判失败、杀残留执行体、释放额度、告警)一律挂在 CAS 认领之后,多个副本同时扫到同一具僵尸,只有 CAS 赢家真正执行,否则告警发两遍就是新的双跑;kill 以外部权威收敛——执行体都在 K8s 里,按标签删 pod,任何副本都能杀,不依赖某个副本内存里的执行句柄。

slot 分片:从「不出错」到「不白干」。到此正确性已闭环,但 N 个副本扫同一批行、N-1 个在 CAS 上扑空,吞吐不随副本数涨。解法是 DolphinScheduler 式取模分片:成员发现就一张 MySQL 心跳表,每副本周期性 upsert 自己一行,活成员按节点 ID 排序定出自己的 slot,扫描时只捞「id 取模等于自己 slot」的那片。稳态下零重复扫描、零 CAS 争抢,吞吐近似线性;扩缩容是「无状态重算」,十秒级自动再均衡,没有任何迁移动作。

成员视图短暂不一致怎么办?不怎么办,CAS 兜底:分片重叠,最坏多一次扑空;分片有缝,视图偏小的副本覆盖面更宽,漏不掉。这是整套架构最关键的性质——

分片只是吞吐优化,永远不是正确性边界。心跳表哪怕整个被清空、滞后、彻底不一致,系统也只退化成「全扫 + CAS」:慢一点,绝不出错。

唯一的悲观锁留给了资源配额准入(共享计数器的「读-算-写」,CAS 不适合),配套一条容易踩空的纪律:锁定读必须是事务里的第一条读,否则 REPEATABLE READ 的快照会让锁内读到过期用量,并发下配额直接超卖。

多副本之下,DAG 工作流照常编排、运维侧照常可观测,这些能力在「我的数据空间」(产品介绍)里长这样:

四、适用边界

需要毫秒级成员感知(在线服务路由级的故障切换)、需要真 fencing token(被抢占者持有的资源无法由 K8s 这类外部权威收敛)、协调事件高频到关系库扛不住,或跨区域部署——这四种场景该老实上 ZK/etcd。反之,已有一个大家都写的关系库、协调决策是秒级低频、执行体可由外部权威收敛,就不需要为 HA 引入任何新组件。

五、三句话总结

  • 选主解决「谁干活」,CAS 直接解决「每件事只干一次」——后者才是目标性质;
  • 正确性与吞吐拆成两层:CAS 保正确,分片只管加速,任何一层糙一点系统都不出错;
  • 依赖清单每多一项,可用性是乘法——正确性只押在系统里本来就必须活着的那个组件上。

这套调度器是「我的数据空间」的一部分——一套可私有化部署的数据平台,支持 OEM 合作。产品介绍:https://datastudiohappy.cn/。

http://www.cnnetsun.cn/news/4118637.html

相关文章:

  • RTL8720DN双模物联网SoC开发:从硬件架构到低功耗实战
  • 脑机接口实战:用Python实现脑电波意念控制与信号处理
  • Sib:用Git版本控制管理AI对话历史的命令行LLM客户端
  • 1.6T光模块:技术演进、市场现状与工程挑战深度解析
  • 【YOLO26创新改进】TIP顶刊 2023 | Conv创新改进篇 | 利用 CSFCN 上下文与空间特征校准网络,使网络能够获得更准确的语义信息,适合目标检测、语义分割、图像分割任务,高效涨点
  • TrenchesWIP:一战战术射击游戏入门指南与BOT对战技巧
  • 信息技术EI期刊发表全攻略:从选刊到检索的实战指南
  • B站视频下载终极指南:免费开源工具一键保存4K大会员与充电专属视频
  • 华为认证高频易错题库解析:攻克IP计算、网络设备与协议核心难点
  • Python实现LSTM时间序列预测教程
  • 让2011年的老Mac跑上macOS Sequoia:OpenCore Legacy Patcher 一次点亮的完整上手指南
  • 电视浏览器(CCTV_Viewer):观看央视卫视直播的安卓 TV 盒子
  • Go源码分析:Mutex与读写锁实现
  • AI如何从混沌中看见世界?解析非结构化数据处理的算法演进与工程实践
  • 保时捷Taycan核心技术解析:800V架构与两速变速箱如何重塑电动性能标杆
  • WSL 2原生Docker环境搭建:告别Docker Desktop,打造高效容器开发平台
  • ExComm:构建抗错多智能体通信,实现测试时稳定扩展
  • DS 3 Crossback E-Tense改款前瞻:三电升级与智能座舱革新
  • OpenAI高管教网友用Claude跑GPT-5.6 Sol,开发者照做却被封号,CC之父火速下场回应后还想挖角却遭拒
  • 可白嫖源码---课程设计--毕业设计--springboot高校新生报到管理系统[编号:project17415](案例分析)-附源码
  • 零基础快速上手:歌词滚动姬完整指南,免费网页版LRC歌词制作工具
  • 基于java的城市公交调度系统
  • Steam 创意工坊下载新思路:WorkshopDL 免费一键打包模组,完整上手教程
  • LLM 推理成本优化:KV Cache 调优与生产部署的降本实战
  • Gopeed下载唤醒失败?3道关卡自检,磁力链接5分钟恢复响应
  • AI智能体专属电脑配置:Docker、浏览器自动化与Serverless方案详解
  • Content Patcher:不写一行代码,用 JSON 改造你的星露谷世界
  • Windows应用程序0xc000007b错误:从DLL位数错配到系统级修复全解析
  • Montserrat字体从零上手的完整实战手册:选字重、配系列、做排版的 6 个步骤
  • 千首无损音乐批量转MP3:FlicFlac免安装音频格式转换工具实测记录