_bulk 是什么
_bulk 是 Elasticsearch 的批量写入接口:请求体用 NDJSON 组织,动作行与文档行交替出现,支持 index、create、update、delete 四类动作。单条失败不会中断其余条目,因此响应必须逐条检查,只看 HTTP 状态码会漏掉失败项。它是日志采集与批量导入的主力接口,也是往索引写大量文档时最省往返开销的方式。
基本信息
| 格式 | 每行一个 JSON,动作行加文档行成对出现,最后必须有换行 |
|---|---|
| 动作 | index(覆盖)、create(已存在则冲突)、update、delete |
| 常用参数 | ?refresh=wait_for 等待可见,routing 可指定分片 |
| 响应字段 | took、errors、items 数组,逐条含 status 与 result |
| 适用版本 | Elasticsearch 7.x / 8.x |
| 批量大小 | 按几 MB 控制,几百到几千条一批 |
典型使用场景
- 日志采集链路批量落库,减少请求往返
- 数据迁移与重建:把源索引数据写进新索引
- 批量补写字段或纠正文档内容
- 初始化测试数据,一次灌入数千条
- 跨系统同步:外部数据变更后批量写入搜索库
- 批量删除历史数据,按 ID 集合一次提交
示例
示例
POST /_bulk?refresh=wait_for
{ "index": { "_index": "my-index", "_id": "1" } }
{ "title": "a" }
{ "create": { "_index": "my-index", "_id": "2" } }
{ "title": "b" }
{ "update": { "_index": "my-index", "_id": "3" } }
{ "doc": { "title": "c" } }
{ "delete": { "_index": "my-index", "_id": "4" } }
# 注意最后一行也要以换行符结尾,否则解析失败响应逐层读法
| 字段 | 含义 | 关注点 |
|---|---|---|
| took | 整体耗时(毫秒) | 结合批量大小评估吞吐 |
| errors | 是否存在失败项 | 为 true 必须逐条排查 |
| items[].status | 单条 HTTP 状态 | 200/201 成功、409 冲突、400 参数错 |
| items[].result | 写入结果 | created / updated / deleted / noop |
| items[].error | 失败原因 | 类型冲突与版本冲突最常见 |
| items[]._id | 对应文档 ID | 用于回到原始批次定位 |
批量实践要点
- 按体积切批,几 MB 一批比固定条数更稳
- 导入期间把 refresh_interval 调大或设为 -1 提升吞吐
- create 动作适合只允许插入一次的场景,冲突时返回 409
- update 动作默认是部分更新,文档不存在可配 doc_as_upsert
- 删除用 delete 动作比先查再删更省事
- 解析 items 数组时按序号与本地批次对齐,才能定位失败文档
批量失败排查顺序
- 先看响应里 errors 是否为 true
- 过滤 items 里 status 非 2xx 的条目,读 error 的 type 与 reason
- 类型冲突(mapper_parsing_exception)先核对字段映射
- 版本冲突(version_conflict)确认是否并发更新同一文档
- 被拒绝(es_rejected_execution)说明写入队列满,需要限速重试
- 核对成功条数与源数据条数,差值必须补写
响应中 errors 为 true 时要逐条看 items[].error,常见原因是类型冲突与版本冲突,不能只看到 HTTP 200 就认为全部成功。
最后一行缺换行会导致解析失败,脚本拼 NDJSON 时注意补尾换行;动作行与文档行必须成对,delete 动作没有文档行。
单批体积过大会超时或被拒绝,按几 MB 切批;导入完成后恢复 refresh_interval 并手动 refresh 一次。
被拒绝的错误通常是批量并发太高,客户端应做限速与指数退避重试,而不是无限重试把压力堆得更高。
导入限速与重试
- 客户端按批限速,避免把写入队列打满触发拒绝
- 遇到拒绝类错误用指数退避重试,不要立即重放
- 重试前评估重复写入风险:index 动作覆盖安全,create 动作会冲突
- 导入完成后恢复 refresh_interval 并手动 refresh
- 逐批记录失败条目,补写时按原始数组下标对应
- 大批量导入前先在测试索引验证映射与批量参数
导入期间可把副本数临时设为 0 提升写入速度,完成后再调回;这段时间内没有冗余,须选择业务低峰并确认节点健康。
批量请求不需要预先声明动作数量,但动作行与文档行的成对关系必须严格保证;程序生成时建议统一由一个函数拼接,减少手写错行。