2021-04-22

背景

在master-worker中一般会采用全局mq进行任务分发,由worker进行依次拉取任务并执行。但是worker拉取任务是有一定耗时的(具体耗时因mq选型而异),另外在网络抖动等一些情况下,拉取耗时可能会变的很大,且不可控。

解决方案

预拉取

  • worker新增预拉取策略,本地缓存下一个要执行的任务
    • 等当前任务执行完之后,从buffer中取出,同时异步去拉取下一个任务

饥饿模式

上面的方案短板是很明显的,如果worker当前执行任务耗时太久,则会导致下一个任务执行的latency加大。这个是我们不希望看到的。

因此提出饥饿模式,这里我们需要一个manager,它负责维护任务分发等信息,并且我们需要给任务定义以下5种状态

  • 待分发
  • 已分发待执行,(已经分发给worker,等待执行)
  • 执行中,(worker已经在执行)
  • 执行完成
  • 饥饿模式

针对每个任务从分发出去开始,启动一个定时器,如果在一定时间范围内没有被执行,则该任务状态切换为饥饿模式,同时发命令给之前的worker取消执行buffer中的任务(因为是分布式的,任务可能被多次执行,所以需要保证幂等)。

针对饥饿模式的任务,因为已经等待了一定的时间,所以如果重新走任务分发可能也好导致单个任务latency较大,所以可以预启动一些worker做buffer,处理这种饥饿模式下的任务。

具体实现

manager

  • 维护一个已分发待执行的延迟队列,针对已经到期的任务, 执行将原worker删除任务命令 和 任务切换到饥饿模式。
  • 维护一个饥饿模式任务队列,当其不为空的时候,启用buffer-worker。
    • 问题:是否可以强制其他正常worker也先执行这边的任务。(这样的设计感觉有点负责,存疑)

worker

  • 针对本地任务的状态上报,对manager进行上报。manager收到状态变动后,对其状态进行修改。
  • 执行任务并异步拉取下一条任务。
    • 如果本地没有队列,向manager同步拉取并阻塞住。
  • 对worker而言,其自身不应该意识到自己是normal还是buffer。尽量让其执行任务和任务流转状态保持一致。

QA

饥饿模式名词的由来

参考自 go Mutex的设计:https://github.com/golang/go/blob/master/src/sync/mutex.go#L42

mutex等待队列中第一个goroutine在长时间抢占不到锁的时候,会将mutex切换到饥饿模式(starvation)。该模式下其他goroutine将不会再尝试抢占锁,这样就在一定程度上保证了goroutine抢占锁的公平性。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 关于《电力企业内训师系统培养方案》企业培训是人力资源开发...
    师资供应阅读 396评论 0 0
  • 时间:2021年4月22日(星期三)下午5:30左右 地点:操场 人物:豆豆(4岁)、明明(3岁10个月)、辰辰(...
    柳柳说说阅读 274评论 0 0
  • 要提高企业效率,管理真的很重要 中国向来有“家和万事兴”的说法,兵法中除了...
    2华典智慧阅读 351评论 0 0
  • 外贸邮件有哪些不为人知的小技巧 好的外贸邮件可以带来很多外贸客户咨询,几乎每一个外贸订单的成交都离不开邮件,由此可...
    易家小健阅读 820评论 0 0
  • 30道大概率会考到的题( 11-15题) 本章内容 11,箭头函数特点 12,CSS盒模型 13,Vue组件dat...
    小王子__阅读 527评论 0 1