遇到一个工人分工干活的问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
morefreeze
V2EX    程序员

遇到一个工人分工干活的问题

  •  
  •   morefreeze 2017-02-28 17:32:32 +08:00 3482 次点击
    这是一个创建于 3146 天前的主题,其中的信息可能已经有所发展或是发生改变。

    假设我有 n 个工人,我可以让他们干活或者同步地检查别人是否完成了工作。

    有两个任务 A 和 B , B 需要有 m 个任务 A 完成了才能执行,所以我就要抽调 m 个工人去监工,但当 m>n 时,就会导致没有人实际在工作,就死锁了。

    但 n 不能设得>m ,因为如果有 m 个工人都在干活的话,内存会不够。

    请问这问题咋解决?

    目前我能想到的策略是降低监工的优先级,保证干活的人最先执行,让监工更快地返回结果,增加重试次数(相当于是个异步了)。说到底还是平衡监工和干活人的数量。

    10 条回复    2017-03-02 12:04:37 +08:00
    casparchen
        1
    casparchen  
       2017-02-28 19:06:48 +08:00 via iPhone
    完成工作后主动报告不好吗,为什么要监工
    snnn
        2
    snnn  
       2017-02-28 21:14:21 +08:00 via Android
    创建 task A 的时候传递一个原子类型的计数器进去。每完成一个就减一。减到 0 就 submit task B 。
    没有监工。 no wait
    exch4nge
        3
    exch4nge  
       2017-03-01 09:36:20 +08:00
    简单的解决方法就像 @snnn 写的一样,不用什么监工。
    复杂情况下,一般会安排一个工长(任务调度线程),负责分配任务, B 任务的前置条件如果没有满足,就不分配 B 任务。
    morefreeze
        4
    morefreeze  
    OP
       2017-03-01 12:07:16 +08:00
    @casparchen 老哥你这话说的就像问:我的程序慢咋办啊?加内存加机器就好了啊。在目前的框架下无法做到异步的
    @snnn @exch4nge 靠点谱,我也许可以找些别的方法把监控 m 个任务改成监控一个变量 m ,当然也要保证 m 会被正确地减去,比如我原先要求[1,2,3,4,5]完成,而[1,2,2,4,5]虽然也是 5 个,但完成的人不对也不行。
    exch4nge
        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]?
    Youen
        6
    Youen  
       2017-03-01 14:05:11 +08:00
    morefreeze
        7
    morefreeze  
    OP
       2017-03-01 16:02:43 +08:00
    @exch4nge (你们说的)靠点谱,你咋就理解成贬义呢,我的意思就是你们说的有些道理,给了我启发
    至于我最后说的[1,2,3,4,5]还是无视掉吧,我确实没在题目中说明,我只是自言自语提醒自己注意这个情况。
    另外回下你在 3 楼的方法,你说的其实就是“我”的工作,我就是一个调度器,我在指挥工人做事(包括干活和监视别人),你说检查任务 B 前置条件是否满足实际就是派工人去监工,但因为用的框架所限,他是同步阻塞的,我让一个工人去监工了,那这个工人只能等着,啥都干不了。

    多说点,我说监工的是 airflow 中的 ExternalTaskSensor ,干活指可以执行功能的 Operator (比如 BashOperator ),避免过多背景介绍,抽象成了这个问题
    https://airflow.incubator.apache.org/code.html?highlight=response#airflow.operators.ExternalTaskSensor
    snnn
        8
    snnn  
       2017-03-01 18:35:57 +08:00 via Android
    @morefreeze 你脑子转个弯啊。假如 worker 有 ID 区分,那把 int 换成 set<int>就行了
    exch4nge
        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 好像情况稍微类似。
    morefreeze
        10
    morefreeze  
    OP
       2017-03-02 12:04:37 +08:00
    @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 分别管理监工和工人(从根本解决问题)
    进程间通信(解决问题,增加复杂度)
    配置一个较好的重试策略,调低监工优先级,监工较快返回结果,较多的重试(理论上点背的话还是会死锁,但降低概率)
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5382 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 36ms UTC 09:13 PVG 17:13 LAX 02:13 JFK 05:13
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86