其他分享
首页 > 其他分享> > spring – 使用zookeeper在集群中计划的任务

spring – 使用zookeeper在集群中计划的任务

作者:互联网

我们使用Spring来运行可以在单个节点上正常工作的计划任务.我们希望在N个节点的集群中运行这些计划任务,以便在一个时间点由一个节点执行任务.这是针对企业用例的,我们可能期望多达10到20个节点.

我研究了各种选择:

>使用Quartz,它似乎是在群集中运行计划任务的流行选择.缺点:我想避免的数据库依赖.
>使用zookeeper并始终仅在leader / master节点上运行计划任务.缺点:未分配任务执行负载
>使用zookeeper并在所有节点上调用计划任务.但是在任务运行之前,一旦执行完成,就获得分布式锁定和释放.
缺点:所有节点上的系统时钟应该同步,如果应用程序过载导致系统时钟漂移,这可能是一个问题.
>使用zookeeper并让主节点按照计划继续生成任务并将其分配给随机工作者.如果尚未处理先前的计划任务,则不会分配新任务.缺点:这似乎增加了太多的复杂性.

我倾向于使用#3,这似乎是一个安全的解决方案,假设zookeeper集合节点在一个单独的集群上运行,系统时钟使用NTP同步.这也是假设如果系统时钟同步,则所有节点都有相同的机会获取锁以执行任务.
编辑:经过一番思考后,我意识到这可能不是一个安全的解决方案,因为系统时钟应该在运行计划任务的节点之间同步,而不仅仅是zookeeper集群节点.我说不安全,因为运行任务的节点可能因GC暂停和其他原因而过载,并且时钟可能不同步.但我再次认为这是分布式系统的标准问题.

如果我对每个选项的理解准确,您能否告诉我?或者可能有比列出的选项更好的方法来解决这个问题.

解决方法:

好吧,你可以像这样改进#3.

Zookeeper提供观察者.也就是说,您可以在给定的ZNode上设置观察者(例如在路径/某些/路径上).群集中的所有节点都在观看相同的节点.每当一个节点认为(按计划或任何方式)它现在应该运行计划任务,

>首先,它在/ some / path下创建一个PERSISTENT_SEQUENTIAL子节点(所有节点都在观察).此外,您可以根据需要设置该节点的数据.它可以是一个json字符串,指定有关要运行的任务的详细信息.新的ZNode路径看起来像/ some / path / prefix_< sequence-number>.
>然后,将通知群集中的所有节点有关创建的子节点.然后,所有这些都获取新创建的ZNode数据并解码任务.
>现在,每个节点都尝试获取分布式锁.谁先获得它可以执行它.一旦执行,该节点应报告(通过在/ some / path / prefix_< sequence-number>下创建新的ZNode,名称成功),该任务已执行.然后释放锁.
>每当节点尝试执行任务时,在尝试获取分布式锁之前,应检查该ZNode是否已有成功子节点.

此设计通过在创建的给定ZNode下检查具有名称成功的子节点来确保没有任务运行两次,以通知启动任务.

我已将上述设计用于企业解决方案.实际上对于分布式命令框架;-)

标签:spring,apache-zookeeper,distributed-system,apache-curator,spring-scheduled
来源: https://codeday.me/bug/20190710/1429026.html