📣 极限科技诚招搜索运维工程师(Elasticsearch/Easysearch)- 全职/北京 👉 : 立即申请加入

适用版本: 7.11-8.9

1. 错误说明 #

failed to start rollup task 表示 Elasticsearch 在尝试启动 Rollup 任务时,内部的 indexer.start() 方法未能返回 IndexerState.STARTED 状态,导致任务启动流程被中断并抛出异常。

Rollup 是 Elasticsearch 提供的一种历史数据降采样机制,用于将高频细粒度数据按时间窗口聚合后写入目标索引,从而降低存储成本并提升历史数据查询效率。当 Rollup Job 被创建并提交后,Elasticsearch 会尝试启动一个异步 indexer 来执行滚动聚合任务;如果 indexer 无法正常进入 STARTED 状态,就会触发此异常。

常见现象 #

  • 调用 _rollup/start API 后任务状态始终为 stoppedaborting,无法进入 started
  • 在 Elasticsearch 日志中可以看到 failed to start rollup task 异常信息。
  • 目标 rollup 索引中没有任何聚合数据写入,历史数据降采样流程完全中断。
  • 如果任务反复尝试启动,可能会在日志中观察到大量失败重试记录,伴随节点资源消耗升高。

典型报错 #

ElasticsearchException: failed to start rollup task
    at org.elasticsearch.xpack.rollup.RollupJobTask$1.onFailure(RollupJobTask.java:XX)
Caused by: java.lang.IllegalStateException: Indexer not in STARTED state

2. 原因分析 #

从源码层面看,Rollup 任务启动的核心逻辑如下:

if (indexer.start() == IndexerState.STARTED) {
    indexer.maybeTriggerAsyncJob(Long.MAX_VALUE);
} else {
    listener.onFailure(new ElasticsearchException("failed to start rollup task"));
}

indexer.start() 返回的状态不是 IndexerState.STARTED 时,就会触发此异常。常见根因包括:

  • Rollup Job 配置非法source_index 不存在或已被删除;cron 表达式格式错误;groupsmetrics 中引用了不存在的字段或使用了不支持的聚合类型。
  • 源索引状态异常:源索引处于 close 状态、索引分片未分配完成、或索引存在 index.read_only_allow_delete 阻塞。
  • 任务状态冲突:同名 Rollup Job 已在其他节点上运行,或之前的任务实例未正常清理,导致 indexer 无法获取执行权。
  • 目标索引问题:目标 rollup 索引已存在但 mapping 与当前聚合配置不兼容,或目标索引所在节点磁盘空间不足。
  • 节点资源不足:节点 JVM 堆内存压力大、线程池(rollup 线程池)已满,导致 indexer 无法被正常调度。
  • 集群状态不稳定:在任务启动瞬间集群发生 master 漂移、节点加入/离开,导致任务上下文丢失。

3. 解决方案 #

步骤一:检查 Rollup Job 配置 #

使用以下 API 查看当前 job 的配置详情:

GET _rollup/job/<job_id>

重点检查以下字段:

  • source_index:确认索引存在且处于 open 状态。
  • cron:确认表达式合法,可使用 cron 在线工具 验证。
  • groups.date_histogram.field:确认时间字段在源索引中存在且类型为 date
  • metrics:确认引用的字段类型和聚合函数匹配(如 max/min 仅适用于数值字段)。

步骤二:检查任务状态与节点日志 #

查看任务当前状态:

GET _rollup/job/<job_id>/_stats

同时检查 Elasticsearch 节点日志,搜索关键字:

grep -i "rollup\|failed to start" /var/log/elasticsearch/elasticsearch.log

步骤三:确认索引状态 #

检查源索引和目标索引的健康状态:

GET _cat/indices/<source_index>,<target_index>?v
GET _cluster/allocation/explain

如果源索引被关闭,需要先打开:

POST <source_index>/_open

步骤四:清理冲突状态后重启任务 #

如果任务状态异常,先停止任务:

POST _rollup/job/<job_id>/_stop

确认任务已停止后,再重新启动:

POST _rollup/job/<job_id>/_start

步骤五:检查节点资源 #

查看节点线程池状态,确认 rollup 线程池是否正常:

GET _cat/thread_pool/rollup?v
GET _nodes/stats/thread_pool

如果 JVM 堆压力过高,考虑扩容或优化查询负载后再启动任务。

4. 预防措施 #

  • 配置校验前置:在创建 Rollup Job 前,使用 PUT _rollup/job/<job_id> 的 dry-run 模式(或先在测试环境验证)确认配置合法。
  • 源索引生命周期管理:为源索引设置合理的 ILM 策略,避免索引被意外关闭或删除;对历史数据使用 delete 而非 close 操作。
  • 资源监控告警:对 rollup 线程池队列长度、JVM 堆使用率、磁盘剩余空间设置告警阈值,在资源不足时提前介入。
  • 任务状态巡检:定期通过 _rollup/job/_all/_stats 检查所有 rollup 任务状态,及时发现 stoppedaborting 状态的异常任务。
  • 版本兼容性注意:Rollup 功能在 Elasticsearch 7.x 中处于试用状态,8.x 中已标记为弃用(deprecated),建议在新版本中优先考虑 Data Streams 配合 downsampling 替代方案。

5. 相关错误 #

附:日志上下文 #

以下为触发此异常的源码片段,便于结合完整异常栈定位问题:

// RollupJobTask.java
if (indexer.start() == IndexerState.STARTED) {
    indexer.maybeTriggerAsyncJob(Long.MAX_VALUE);
} else {
    listener.onFailure(new ElasticsearchException("failed to start rollup task"));
}