假设我有 n 个工人,我可以让他们干活或者同步地检查别人是否完成了工作。
有两个任务 A 和 B , B 需要有 m 个任务 A 完成了才能执行,所以我就要抽调 m 个工人去监工,但当 m>n 时,就会导致没有人实际在工作,就死锁了。
但 n 不能设得>m ,因为如果有 m 个工人都在干活的话,内存会不够。
请问这问题咋解决?
目前我能想到的策略是降低监工的优先级,保证干活的人最先执行,让监工更快地返回结果,增加重试次数(相当于是个异步了)。说到底还是平衡监工和干活人的数量。
1
casparchen 2017-02-28 19:06:48 +08:00 via iPhone
完成工作后主动报告不好吗,为什么要监工
|
2
snnn 2017-02-28 21:14:21 +08:00 via Android
创建 task A 的时候传递一个原子类型的计数器进去。每完成一个就减一。减到 0 就 submit task B 。
没有监工。 no wait |
3
exch4nge 2017-03-01 09:36:20 +08:00
简单的解决方法就像 @snnn 写的一样,不用什么监工。
复杂情况下,一般会安排一个工长(任务调度线程),负责分配任务, B 任务的前置条件如果没有满足,就不分配 B 任务。 |
4
morefreeze OP @casparchen 老哥你这话说的就像问:我的程序慢咋办啊?加内存加机器就好了啊。在目前的框架下无法做到异步的
@snnn @exch4nge 靠点谱,我也许可以找些别的方法把监控 m 个任务改成监控一个变量 m ,当然也要保证 m 会被正确地减去,比如我原先要求[1,2,3,4,5]完成,而[1,2,2,4,5]虽然也是 5 个,但完成的人不对也不行。 |
5
exch4nge 2017-03-01 13:36:33 +08:00
@morefreeze 所以你还是没在题目里描述清楚为什么需要监工以及 A 、 B 任务相关的详细信息。你没有把问题描述清楚,那 @snnn 跟我说的不能说不靠谱吧。
按你这个评论的意思就是工人也有区分?却任务 A 是一样的任务 A ?那要求[1,2,3,4,5],就不能是[1,6,2,4,5]? |
6
Youen 2017-03-01 14:05:11 +08:00
|
7
morefreeze OP @exch4nge (你们说的)靠点谱,你咋就理解成贬义呢,我的意思就是你们说的有些道理,给了我启发
至于我最后说的[1,2,3,4,5]还是无视掉吧,我确实没在题目中说明,我只是自言自语提醒自己注意这个情况。 另外回下你在 3 楼的方法,你说的其实就是“我”的工作,我就是一个调度器,我在指挥工人做事(包括干活和监视别人),你说检查任务 B 前置条件是否满足实际就是派工人去监工,但因为用的框架所限,他是同步阻塞的,我让一个工人去监工了,那这个工人只能等着,啥都干不了。 多说点,我说监工的是 airflow 中的 ExternalTaskSensor ,干活指可以执行功能的 Operator (比如 BashOperator ),避免过多背景介绍,抽象成了这个问题 https://airflow.incubator.apache.org/code.html?highlight=response#airflow.operators.ExternalTaskSensor |
8
snnn 2017-03-01 18:35:57 +08:00 via Android
@morefreeze 你脑子转个弯啊。假如 worker 有 ID 区分,那把 int 换成 set<int>就行了
|
9
exch4nge 2017-03-01 21:48:07 +08:00 1
@morefreeze 首先对“靠点谱”的贬义理解道个歉,刚刚花半小时看了下 airflow ,之前没接触过,下面我说的可能会有错误。
Airflow 本身就是一个对任务进行规划、定期执行的框架,我看到 DAG 是可以规划多个任务及依赖关系。 不过看你用了 ExternalTaskSensor ,估计是没办法把任务 A 与任务 B 放到一个 DAG 里,如果能放在一个 DAG 里那更简单了。 其实不考虑 airflow 这个背景框架,确实可以用一个数据结构来存储 task 的完成情况,例如 @snnn 说的那样,然后保证这个数据结构的读写是原子操作就可以了,不过这个就限制在同一个进程内了( airflow 可能不是吧, airflow 是不是分布式的?)。 在 airflow 这个框架背景下,可以用框架提供的 XComs 做 task 间通信,原来的监工 task 可以改成一个,不用 ExternalTaskSensor ,而是通过收集其它 task 发来的信息,等待合适时机,发布任务 b 。 https://issues.apache.org/jira/browse/AIRFLOW-47 好像情况稍微类似。 |
10
morefreeze OP @snnn 对对对,是这么想的,但其实我是要知道 worker 执行的 task ID ,这个问题我自己能解决
@exch4nge 感谢热心帮助,其实没必要去了解这些 放在一个 DAG 肯定是可以的,但这就像一个项目也可以把代码放在一个文件里一样 airflow 是可以分布式执行,但比如任务信息这些都存在数据库里,由一个 scheduler 来统一管理 XComs 也是种解决办法,我觉得可行。 我在 sto 上提问也得到了比较好的解决办法, http://stackoverflow.com/questions/42504185/airflow-celery-worker-will-be-blocked-if-sensor-number-large-than-concurrency/42510574#42510574 利用 Pool 来限制 ExternalTaskSensor 最大执行数量,这样相当于把监工和工人隔离开了,我之前也不知道有这个技巧。 总结下这个问题思路: 划分监工和工人的执行,比如 Pool 的概念,或者启两个 scheduler 分别管理监工和工人(从根本解决问题) 进程间通信(解决问题,增加复杂度) 配置一个较好的重试策略,调低监工优先级,监工较快返回结果,较多的重试(理论上点背的话还是会死锁,但降低概率) |