2025年12月08日/ 浏览 29
标题:分布式定时任务那些事儿|青训营笔记
关键词:分布式定时任务、调度系统、任务分片、容错机制、青训营
描述:本文深入探讨分布式定时任务的核心技术,包括架构设计、任务分片策略、容错机制实现,并结合实际场景分析典型问题的解决方案。
正文:
当单机定时任务面临百万级任务调度时,你会遇到两个致命问题:性能瓶颈和单点故障。去年我们电商大促时,就因为单机定时任务崩溃导致优惠券发放延迟,直接损失300万订单——这就是我们转向分布式方案的契机。
典型架构包含三个角色(以Apache DolphinScheduler为例):
mermaid
graph TD
A[Master节点] -->|任务派发| B[Worker节点]
B -->|心跳上报| C[ZooKeeper]
C -->|选举协调| A
// 伪代码示例:任务派发逻辑
void dispatchTask(Task task) {
if (zk.getActiveMasters() < 3) {
throw new RuntimeException("Master节点不足");
}
Worker worker = loadBalance.selectWorker();
worker.execute(task);
}
关键点:
- Master采用Leader-Follower模式避免脑裂
- Worker通过心跳包上报资源利用率
- 调度决策需考虑跨机房延迟(实测上海-北京机房RTT约35ms)
我们曾用一致性哈希分片导致20%任务倾斜,后来改进为动态权重分片:
| 分片算法 | 适用场景 | 缺点 |
|----------|----------|------|
| 轮询分配 | 均匀任务 | 忽略节点负载 |
| 哈希取模 | 固定路由 | 扩容困难 |
| 动态权重 | 弹性伸缩 | 实现复杂 |
// 动态分片示例
List<Shard> shard(Task task, List<Worker> workers) {
return workers.stream()
.sorted(comparing(Worker::getCpuLoad).reversed())
.limit(task.getShardCount())
.map(w -> new Shard(w, task.getDataSlice()))
.collect(toList());
}
支付系统中遇到的典型案例:
mermaid
sequenceDiagram
定时任务->>+DB: 查询待处理订单
DB-->>-定时任务: 返回100条记录
定时任务->>+MQ: 发送支付消息
MQ-->>-消费者: 网络抖动导致ACK丢失
定时任务->>MQ: 重复发送(灾难!)
解决方案:
boolean isProcessed(String bizId) {
return redis.setnx("lock:"+bizId, "1", 24*3600) == 1;
}
(完)