面试题答案
一键面试设计思路
- ElasticSearch 特性利用
- 文档存储:将定时任务相关信息(如任务ID、执行时间、任务详情等)以文档形式存储在ElasticSearch索引中。每个任务对应一个文档,通过文档唯一标识任务。
- 时间单位API:利用ElasticSearch支持的时间类型和时间范围查询功能,精确控制任务执行时间。例如,使用
date
类型字段记录任务计划执行时间,通过range
查询获取即将执行的任务。
- 分布式算法
- 任务分配算法:采用基于权重的任务分配算法。为每个节点分配一个权重值,权重可根据节点的硬件资源(如CPU、内存等)动态调整。在任务分配时,优先将任务分配给权重高的节点,以充分利用资源。
- 任务协调:使用分布式锁机制,确保同一任务不会在多个节点同时执行。例如,利用ElasticSearch的乐观锁(通过版本号控制)实现分布式锁。当一个节点尝试获取任务执行权时,首先获取任务文档的当前版本号,然后以该版本号为条件尝试更新任务文档(如标记任务为执行中),如果更新成功,则获取到锁,可执行任务;否则,等待并重试。
- 处理网络分区问题
- 节点健康检查:定期通过ElasticSearch的集群状态API检查节点健康状况。每个节点定时向ElasticSearch集群发送心跳信息(如通过更新节点状态文档),其他节点通过监控这些文档来判断节点是否存活。
- 网络分区检测:基于ElasticSearch的集群状态变化,检测是否发生网络分区。当网络分区发生时,不同分区内的节点可能会形成多个小集群。通过对比不同节点获取的集群状态信息,判断是否存在网络分区。
- 任务重新分配:一旦检测到网络分区,并且分区恢复后,对任务进行重新分配。对于在网络分区期间未执行的任务,重新评估节点权重,按照任务分配算法重新分配给可用节点执行。
具体实现步骤
- 任务文档结构设计
在ElasticSearch中创建一个索引,每个任务文档包含以下字段:
task_id
:任务唯一标识符。execution_time
:任务计划执行时间(date
类型)。task_status
:任务状态,如“待执行”、“执行中”、“已完成”、“失败”等。task_detail
:任务具体执行逻辑(如脚本内容、方法调用等)。assigned_node
:当前分配执行任务的节点标识。
- 任务调度流程
- 任务添加:将新任务以文档形式写入ElasticSearch索引,设置
task_status
为“待执行”,assigned_node
为空。 - 任务分配:每个节点定期查询ElasticSearch,获取即将执行且
task_status
为“待执行”的任务。根据权重计算,每个节点尝试获取任务执行权,通过更新任务文档标记task_status
为“执行中”并设置assigned_node
为自身节点标识。 - 任务执行:获取到任务执行权的节点,按照
task_detail
中的逻辑执行任务。执行完成后,更新任务文档的task_status
为“已完成”或“失败”,并记录相关执行结果。 - 节点故障处理:当某个节点发生故障时,其他节点通过节点健康检查发现该节点异常。对于该故障节点上处于“执行中”的任务,将其
task_status
重新设置为“待执行”,assigned_node
清空,以便重新分配执行。
- 任务添加:将新任务以文档形式写入ElasticSearch索引,设置
通过以上设计思路和实现步骤,可以构建一个基于ElasticSearch时间单位API的高可用定时任务框架,确保任务在分布式系统中协同执行,不重复、不遗漏,并能应对节点故障和网络分区等问题。