适用版本: 7.17-8.9
1. 错误异常的基本描述 #
failed to create new translog file 表示 Elasticsearch 在创建新的 translog writer 文件时抛出了 IOException,随后被包装成 TranslogException。该异常发生在写入链路的最底层——translog 持久化阶段,意味着索引操作无法安全地写入事务日志,通常会直接影响分片的可写性和恢复能力。
常见现象 #
- 索引写入请求失败,返回
500或429状态码,具体取决于是否触发了熔断或重试逻辑。 - 分片状态可能变为
RED或YELLOW,尤其在分片恢复、滚动重启或磁盘压力较大的场景下。 - 节点日志中会出现
TranslogException: failed to create new translog file异常,并伴随IOException原因链。 - 如果问题持续存在,可能会导致分片无法分配、索引无法打开,甚至触发索引级别的只读保护。
典型报错与异常栈 #
该异常在日志中通常表现为以下形式:
org.elasticsearch.index.translog.TranslogException: failed to create new translog file
Caused by: java.io.IOException: No space left on device
at java.io.FileOutputStream.open0(Native Method)
at java.io.FileOutputStream.open(FileOutputStream.java:270)
at org.elasticsearch.index.translog.Translog.createWriter(Translog.java:xxx)
或:
TranslogException[failed to create new translog file]
Caused by: java.nio.file.AccessDeniedException: /var/lib/elasticsearch/nodes/0/indices/xxx/0/translog/translog-xxx.tlog
2. 为什么会发生这个错误 #
Translog(事务日志)是 Elasticsearch 保证数据可靠性的核心组件。每次索引操作(写入、更新、删除)在写入 Lucene 内存缓冲之前,都会先被记录到 translog 中。当 translog 文件大小达到阈值(默认 512MB)或发生 flush 操作时,Elasticsearch 会创建一个新的 translog 文件来继续接收写入。
如果在创建新 translog 文件的过程中,底层文件系统操作失败,就会抛出此异常。常见原因包括:
- 磁盘空间不足:数据分区使用率接近 100%,文件系统无法分配新的 inode 或数据块。
- 磁盘 inode 耗尽:即使磁盘空间尚有剩余,但 inode 数量已用完,同样无法创建新文件。
- 文件权限异常:Elasticsearch 进程对分片数据目录(
$ES_PATH_DATA/nodes/0/indices/)没有写权限,常见于目录被手动修改权限或迁移后未正确授权。 - 文件系统只读挂载:磁盘出现 I/O 错误后被系统自动重新挂载为只读模式(
ro),导致所有写操作失败。 - 文件句柄耗尽:操作系统级别的文件描述符(file descriptor)达到上限,无法打开新文件。
- 磁盘硬件故障或 I/O 抖动:底层存储出现坏道、I/O 超时或存储驱动异常,导致文件创建操作失败。
- 分片目录损坏:分片数据目录被外部进程意外修改或删除,导致 translog 目录结构不完整。
3. 如何排查这个异常 #
建议按照"先确认影响范围,再定位根因"的顺序排查:
- 确认异常影响范围:检查是个别分片报错,还是整个节点甚至多个节点同时出现。单个分片异常往往指向目录权限或局部磁盘问题;多节点同时报错则更可能是存储系统层面的问题。
- 检查磁盘空间与 inode:在节点上执行
df -h和df -i,确认数据分区使用率是否超过 90%,以及 inode 是否耗尽。 - 检查文件系统挂载状态:执行
mount | grep <data_path>确认数据目录所在分区是否为读写模式(rw),而非只读(ro)。 - 检查 Elasticsearch 进程权限:确认
$ES_PATH_DATA目录及其子目录的所有者和权限是否正确,Elasticsearch 进程用户是否拥有写权限。 - 检查文件句柄限制:查看 Elasticsearch 日志中是否有
too many open files相关报错,并对比ulimit -n的当前值和配置值。 - 查看系统日志:检查
/var/log/syslog、dmesg或硬件监控平台,确认是否有磁盘 I/O 错误、文件系统报错或存储链路告警。 - 结合时间窗口分析:确认异常发生前后是否有磁盘迁移、节点重启、索引删除或操作系统补丁变更等操作。
排查时需要注意的问题 #
- 不要只关注 translog 报错本身,磁盘问题往往会同时触发多种异常(如
engine 启动失败、translog 损坏、segment 文件写入失败等),需要综合研判。 - 如果节点已被标记为磁盘水位超限(
high disk watermark),Elasticsearch 会自动将该节点上的分片迁走,此时 translog 创建失败可能是迁移过程中的连带问题。 - 在容器化部署(Docker/K8s)场景下,还需确认宿主机磁盘和容器存储卷的映射关系是否正确,以及是否有存储卷容量限制(PVC quota)。
4. 如何解决这个错误 #
常用修复思路 #
- 磁盘空间不足:清理过期数据、删除不需要的索引、扩容磁盘,或临时调高磁盘水位线(
cluster.routing.allocation.disk.watermark)以恢复写入。 - inode 耗尽:查找并清理大量小文件(常见于 translog 或 segment 文件堆积),必要时重新格式化文件系统时指定更大的 inode 数量。
- 权限问题:修正数据目录权限,例如执行
chown -R elasticsearch:elasticsearch $ES_PATH_DATA和chmod -R 750 $ES_PATH_DATA。 - 文件系统只读:先排查磁盘硬件健康状态,确认无硬件故障后,尝试重新以读写模式挂载分区:
mount -o remount,rw <device> <mount_point>。 - 文件句柄耗尽:修改系统限制,在
/etc/security/limits.conf中增加elasticsearch soft nofile 65536和elasticsearch hard nofile 65536,然后重启 Elasticsearch。 - 分片目录损坏:如果确认目录结构损坏且无法修复,可以考虑从副本分片恢复,或通过快照(snapshot)重建索引。
紧急恢复步骤 #
如果业务写入受到严重影响,可以按以下顺序快速止血:
# 1. 临时关闭索引的只读保护(仅在确认磁盘问题已修复后执行)
PUT /<index_name>/_settings
{
"index.blocks.read_only_allow_delete": null
}
# 2. 如果磁盘空间紧张,临时调高磁盘水位线(恢复后记得改回)
PUT _cluster/settings
{
"transient": {
"cluster.routing.allocation.disk.watermark.low": "90%",
"cluster.routing.allocation.disk.watermark.high": "95%"
}
}
# 3. 尝试手动分配因 translog 问题而未被分配的分片
POST /_cluster/reroute?retry_failed=true
后续注意事项与推荐建议 #
- 为磁盘使用率、inode 使用率、文件句柄数和 I/O 延迟设置监控告警,在问题影响业务之前提前介入。
- 定期清理过期索引和旧的 translog 文件,避免磁盘空间被缓慢耗尽。
- 对关键索引保持至少一个副本,确保单节点磁盘故障时可以快速从副本恢复。
- 定期备份数据到远程快照仓库,确保极端情况下可以从快照恢复,而不是依赖可能已损坏的本地 translog。
借助 INFINI 产品提升排障效率 #
- INFINI Console 适合查看集群健康度、节点磁盘使用率、分片分配状态和异常趋势,帮助快速判断 translog 异常是局部磁盘问题还是系统性问题。
- INFINI Gateway 适合部署在 Elasticsearch 前面做请求观测、限流和熔断,在磁盘异常期间减少写入压力,避免更多 translog 相关错误被连锁触发。
- 建议将磁盘告警、分片未分配事件和 translog 异常日志统一接入监控面板,缩短从"发现问题"到"定位根因"的时间。
5. 小结 #
failed to create new translog file 的本质是 translog 新文件创建失败,根因几乎总是落在磁盘、文件系统或操作系统层面的资源限制上,而不是 Elasticsearch 本身的代码缺陷。排查时应优先关注分片本地目录的可写性、磁盘 I/O 健康状态以及操作系统资源限制,而不是请求参数或索引 mapping。只要把磁盘监控、权限管理和容量规划固定下来,这类异常可以在很大程度上被提前预防。
相关错误 #
附:日志上下文 #
下面保留当前页面中的源码或日志片段,便于继续结合异常调用栈定位问题:
bigArrays;
diskIoBufferPool;
operationListener
);
} catch (final IOException e) {
throw new TranslogException(shardId; "failed to create new translog file"; e);
}
return newWriter;
}





