公平分配资源分配共识的推荐算法

问题描述

存在分布式计算节点,并且存在由数据库表中的行(每个任务一行)表示的一组计算任务:

  • 一个节点没有其他节点的信息:不能交谈其他节点,甚至不知道还有多少其他节点
  • 可以添加删除节点,节点可能会死亡并重新启动
  • 仅连接到数据库的节点
  • 每个节点没有任务限制
  • 任务池不是有限的,新任务总是到来
  • 一个节点通过在该行上标记一些时间戳来执行任务,以便其他节点在该时间戳之后经过一段时间(直到节点死亡且未完成任务的情况下)才考虑该行。

目标是在节点之间平均分配任务。为此,我需要定义一些常见的任务获取算法:节点启动时,要执行多少个任务?

如果一个节点执行所有可用任务,则当一个节点始终繁忙而其他节点空闲时。所以这不是一个选择。

一个好的方法是让每个节点在延迟的情况下一对一地执行任务。所以 每个节点定期(一段时间内)检查是否有空闲任务,并且仅执行一项任务。这样,在启动之后不久,所有节点都将获得或多或少均匀分布的所有任务。但是,缺点是由于延迟,要处理最后一个任务会花费一些时间(例如,假设有10000个任务,10个节点,延迟为1秒:它将花费10000个任务* 1秒/ 10个节点=从开始到完成所有任务的时间为1000秒)。另外,分布是不确定的,可能会出现偏斜。

问题:什么样的算法/类可以解决此类问题,从而允许使用某个同步点(在这种情况下为数据库快速而均匀地分配任务,而无需选举领导者

例如:节点使用一些表来宣布它们要执行的任务,然后在进行一些协调步骤之后,它们达成共识并开始处理,等等。

解决方法

因此,这取决于几个因素。

  1. 当前总体上有多少任务可用?
  2. 目前总体上接受多少个任务?
  3. 该节点在最近X分钟内接受了多少个任务。
  4. 该节点在最近X分钟内完成了多少任务。
  5. 行字段可以修改吗? (添加了一个字段)。
  6. 节点可以在完成当前任务后请求更多任务,还是必须立即分发所有任务?

我的意愿是:

  1. 如果可行,请在带有行的表中添加“节点标识符”字段(UUID)。节点在运行时会生成UUID节点标识符。当它接受任务时,会添加一个时间戳和它的UUID。这样,其他节点就可以轻松确定有多少个“活动”节点。
  2. 要确定分配,节点确定有多少个任务可用/已接受。然后,它指出有多少个唯一的节点标识符(包括自身)已接受任务。然后,它使用此公式来接受更多任务(最好是随机执行,以最大程度地减少与其他节点竞争的机会)。 2 * available_tasks / active_nodes - nodes_accepted_tasks。因此,如果有100个可用任务,则有10个活动节点,并且此节点已接受5个任务。然后它将接受:100 / 10 - 5 = 5个任务。如果节点在不再有任何任务时仅寻找更多任务,则可以使用available_tasks / active_nodes
  3. 为避免出现问题,节点一次应接受的最大任务数。

如果节点标识符不切实际。我只想说,每个节点应旨在承担ceil(sqrt(N))个随机任务,其中N是可用任务的数量。如果有100个任务。第一个节点取10,第二个节点取10,第三个节点取9,第4个节点取9,第5个节点取8,依此类推。这不会一次平均分配所有任务,但可以确保节点获得大致均匀数量的任务。 #个任务的轻微错开表示节点将不会全部同时完成任务(这可能是合乎要求的,也可能是不合要求的)。通过不完全分布它们(除非存在sqrt(N)节点),它还减少了冲突的可能性(特别是如果随机选择任务)。如果节点发生故障,它还可以减少“失败”任务的数量。

当然,这假设节点在启动后可以请求更多任务,否则,将变得更加棘手。

对于其他表,您实际上可以使用它来跟踪节点的当前状态。每个节点记录它有多少个任务,唯一的UUID以及上一次完成任务的时间。尽管这可能会引起数据库搅动的潜在问题。我认为仅记录哪个节点已接受任务以及何时接受任务就足够了。如果节点将来可以请求任务,这将再次有用。