串行后处理队列的并行-串行混合架构
在并发编程中,有些任务需要先并行处理再串行汇总。今天我们深入分析一个工业级 串行后处理队列的实现,探索其 并行-串行混合架构 的设计智慧。
场景与需求
这种两阶段处理模式的应用场景:
- 批量数据处理:先并行计算,再串行写入
- 日志收集:先并行聚合,再串行落盘
- 报表生成:先并行统计,再串行生成报告
核心需求:
- 高性能:第一阶段需要并行处理提升吞吐
- 顺序保证:第二阶段需要串行确保顺序
- 资源控制:需要队列大小限制防止内存溢出
解决方案:两阶段队列设计
工业级实现采用了独特的两阶段架构:
// 核心设计:两个队列
IThreadPool* ParallelQueue; // 并行处理队列
THolder<IThreadPool> SerialQueue; // 串行处理队列
// 任务包装
class TAsync {
void Process(void* threadSpecificResource) override {
WorkItem->ParallelProcess();
Done(); // 标记完成
}
};
class TSync {
void Process(void*) override {
Async.Wait(); // 等待并行完成
WorkItem->SerialProcess(); // 串行后处理
}
};
核心设计
TAsync:并行处理
- 在线程池中并行执行
- 完成后通过条件变量通知
TSync:串行包装
- 先加入串行队列
- 等待 TAsync 完成
- 执行 SerialProcess()
Add 流程
bool Add(TAutoPtr<IProcessObject> obj) { TSync* sync = new TSync(obj); // 先加入串行队列 SerialQueue->Add(sync); // 再加入并行队列 IObjectInQueue* async = sync->GetAsync(); ParallelQueue->Add(async); }
权衡分析
优点
- 高性能:并行阶段利用多核
- 顺序保证:串行阶段确保顺序
- 资源控制:可配置队列大小
代价
- 复杂度:两阶段协调增加复杂度
- 延迟:串行阶段可能成为瓶颈
- 内存:任务需要保持直到串行完成
适用场景
- 需要先并行后串行的任务
- 顺序敏感的后处理
- 大批量数据处理
净室重构:Go 实现
下面用 Go 展示同样的设计思想:
type SerialPostProcessQueue struct {
parallelPool *WorkerPool
serialQueue chan *SerialTask
}
// 两阶段处理
func (q *SerialPostProcessQueue) Add(obj ProcessObject) {
task := &SerialTask{
object: obj,
completed: make(chan bool, 1),
}
// 阶段1: 并行处理
q.parallelPool.Submit(func() {
obj.ParallelProcess()
task.completed <- true
})
// 阶段2: 串行处理
q.serialQueue <- task
}
// 串行 worker
go func() {
for task := range q.serialQueue {
<-task.completed // 等待并行完成
task.object.SerialProcess() // 串行后处理
}
}()
运行结果验证了设计:
=== Serial-PostProcess Queue Demo (Go) ===
--- Adding Tasks ---
Added task 1
Added task 2
Added task 3
Added task 4
Added task 5
--- Processing (parallel first, then serial) ---
[Parallel] Task 1 processing...
[Parallel] Task 4 processing...
[Parallel] Task 2 processing...
[Parallel] Task 3 processing...
[Parallel] Task 3 parallel done
[Parallel] Task 5 processing...
...
[Serial] Task 1 post-processing...
[Serial] Task 2 post-processing...
[Serial] Task 3 post-processing...
...
总结
串行后处理队列的并行-串行混合架构体现了 吞吐与顺序的平衡 的工程智慧:
- 两阶段设计:并行提升吞吐,串行保证顺序
- 任务包装:TSync 等待 TAsync 完成
- 资源控制:队列大小限制
- 优雅停机:支持 Stop 等待所有任务完成
这种设计不是"银弹",但对于需要先并行后串行的场景,是一个非常优雅的权衡选择。
系列: Arch (90/90)
系列页
▼