首页
/ Apache DolphinScheduler 任务调度优化:基于工作组分组的优先级队列设计

Apache DolphinScheduler 任务调度优化:基于工作组分组的优先级队列设计

2025-05-18 20:52:55作者:劳婵绚Shirley

背景与问题分析

在分布式任务调度系统Apache DolphinScheduler中,任务调度是一个核心功能。当前版本采用单线程处理所有待调度任务,所有任务都存放在同一个等待队列中。这种设计存在一个明显的性能瓶颈:当某个工作组的任务调度失败时,该任务会被重新放回队列末尾,可能导致高优先级任务被低优先级任务插队。

举例说明:假设工作组W中存在三个优先级为A>B>C的任务,当工作组W负载过高时:

  1. 高优先级任务A调度失败,被放回队列末尾
  2. 系统转而调度优先级次高的任务B
  3. 此时工作组W负载恢复正常,任务B被成功调度
  4. 结果导致低优先级的任务B先于高优先级的任务A执行

这种调度顺序违背了优先级设计原则,影响了系统调度的公平性和效率。

解决方案设计

核心架构改进

新设计方案采用两级队列结构,将任务按工作组进行分组管理:

  1. 全局时间优先队列:保留原有的GlobalTaskDispatchWaitingQueue,但简化为仅按任务提交时间排序
  2. 工作组优先级队列:新增WorkerGroupQueueMap,为每个工作组维护独立的DelayQueue,队列内任务按优先级和超时时间排序

关键数据结构

// 工作组队列中的任务比较逻辑
public int compareTo(@NotNull Delayed o) {
    // 优先比较任务优先级
    int priorityComparison = Integer.compare(this.priority, ((Task) other).priority);
    if (priorityComparison != 0) {
        return priorityComparison;
    }
    
    // 优先级相同则比较超时时间
    return Long.compare(this.startTime, ((Task) other).startTime);
}

线程模型优化

新架构采用双线程协作模式:

  1. 分发线程:从全局队列中按时间顺序获取任务,根据任务所属工作组将其分发到对应的WorkerGroupQueueMap中
  2. 调度线程:从各工作组队列中按优先级获取任务执行,失败时回退到原工作组队列
// 简化的调度逻辑伪代码
doDispatch(){
    // 从全局队列获取任务
    ITaskExecutionRunnable task = GlobalTaskDispatchWaitingQueue.poll();
    // 按工作组分类
    WorkerGroupQueueMap.add(task.getWorkerGroupName(), task);

    // 从各工作组队列获取任务
    Map<String, ITaskExecutionRunnable> tasks = WorkerGroupQueueMap.pollAll();
    for(String workerGroup : tasks.keySet()){
        try {
            dispatchTask(tasks.get(workerGroup));
        } catch (Exception e) {
            // 失败回退
            WorkerGroupQueueMap.add(workerGroup, tasks.get(workerGroup));
        }
    }
}

技术优势

  1. 优先级保障:确保同一工作组内高优先级任务始终优先调度
  2. 隔离性:不同工作组任务互不干扰,避免资源竞争
  3. 弹性扩展:新增工作组时自动创建对应队列,删除时自动清理
  4. 故障恢复:调度失败的任务仅影响同工作组任务,不会波及其他组

实现细节

工作组队列管理

WorkerGroupQueueMap内部维护一个映射表,动态管理工作组与队列的关系:

class WorkerGroupQueueMap {
    private Map<String, DelayQueue<DelayEntry<ITaskExecutionRunnable>>> queueMap;
    
    // 添加任务到指定工作组队列
    public void add(String groupName, ITaskExecutionRunnable task);
    
    // 从各工作组队列获取首个任务
    public Map<String, ITaskExecutionRunnable> pollAll();
}

动态工作组处理

系统通过以下机制保证工作组变更时的队列一致性:

  1. 后台守护线程定期检测工作组变更
  2. 管理API在变更工作组时主动通知Master节点
  3. 新增工作组时自动初始化队列,删除时安全清理

性能影响评估

该改进方案虽然引入了额外的队列管理开销,但带来了显著的调度质量提升:

  1. 调度公平性:严格遵循任务优先级,确保关键任务优先执行
  2. 系统吞吐量:工作组隔离减少锁竞争,提高并发处理能力
  3. 响应时间:高优先级任务获得更快的调度响应

总结

Apache DolphinScheduler通过引入工作组分组队列机制,有效解决了混合队列中的优先级倒置问题。这种设计不仅提升了调度系统的公平性和可靠性,还为后续的功能扩展奠定了基础,如支持更复杂的调度策略、实现细粒度的资源隔离等。该改进方案已在社区达成共识,将成为未来版本的重要优化方向。

登录后查看全文
热门项目推荐

项目优选

收起
ohos_react_nativeohos_react_native
React Native鸿蒙化仓库
C++
178
263
RuoYi-Vue3RuoYi-Vue3
🎉 (RuoYi)官方仓库 基于SpringBoot,Spring Security,JWT,Vue3 & Vite、Element Plus 的前后端分离权限管理系统
Vue
868
514
openGauss-serveropenGauss-server
openGauss kernel ~ openGauss is an open source relational database management system
C++
130
183
openHiTLSopenHiTLS
旨在打造算法先进、性能卓越、高效敏捷、安全可靠的密码套件,通过轻量级、可剪裁的软件技术架构满足各行业不同场景的多样化要求,让密码技术应用更简单,同时探索后量子等先进算法创新实践,构建密码前沿技术底座!
C
288
323
HarmonyOS-ExamplesHarmonyOS-Examples
本仓将收集和展示仓颉鸿蒙应用示例代码,欢迎大家投稿,在仓颉鸿蒙社区展现你的妙趣设计!
Cangjie
398
373
CangjieCommunityCangjieCommunity
为仓颉编程语言开发者打造活跃、开放、高质量的社区环境
Markdown
1.07 K
0
ShopXO开源商城ShopXO开源商城
🔥🔥🔥ShopXO企业级免费开源商城系统,可视化DIY拖拽装修、包含PC、H5、多端小程序(微信+支付宝+百度+头条&抖音+QQ+快手)、APP、多仓库、多商户、多门店、IM客服、进销存,遵循MIT开源协议发布、基于ThinkPHP8框架研发
JavaScript
93
15
note-gennote-gen
一款跨平台的 Markdown AI 笔记软件,致力于使用 AI 建立记录和写作的桥梁。
TSX
83
4
cherry-studiocherry-studio
🍒 Cherry Studio 是一款支持多个 LLM 提供商的桌面客户端
TypeScript
600
58
GitNextGitNext
基于可以运行在OpenHarmony的git,提供git客户端操作能力
ArkTS
10
3