Elasticsearch _bulk API 명령을 사용한 효율적인 데이터 관리
NDJSON 예제, 응답 확인, 배치 크기 조정 및 안전한 재시도 지침을 통해 Elasticsearch _bulk API를 올바르게 사용하는 방법
Elasticsearch _bulk API 명령을 사용한 효율적인 데이터 관리
Elasticsearch _bulk API는 앱이 문서당 하나의 HTTP 요청을 보내지 않고 많은 문서를 인덱싱, 업데이트 또는 삭제해야 할 때 적합한 도구입니다. 사람들이 어려워하는 부분은 요청 본문입니다. 이는 예쁘게 출력된 JSON 배열이 아니라 개행으로 구분된 JSON입니다.
로그를 로드하거나, 다른 데이터베이스에서 레코드를 동기화하거나, 정리 삭제 배치를 적용할 때 _bulk를 사용하세요. 전체 HTTP 요청이 성공하더라도 개별 작업이 실패할 수 있으므로 응답의 모든 항목을 검사해야 합니다.
_bulk API 구조 이해
_bulk API는 일반적으로 NDJSON이라고 하는 개행으로 구분된 JSON을 허용합니다. 각 작업은 한 줄에 정의됩니다. 문서 본문이 필요한 작업은 다음 줄을 소스 또는 업데이트 페이로드로 사용합니다. 마지막 줄도 개행으로 끝나야 합니다.
_bulk 요청의 주요 구성 요소:
- 작업 및 메타데이터 라인: 이 줄은 작업 유형(
index,create,update또는delete), 대상 인덱스 및 선택적으로 문서 ID를 지정합니다. 최신 Elasticsearch API에서는 문서 유형이 사용되지 않습니다. - 소스 라인: 이 줄에는 인덱싱 또는 업데이트할 실제 JSON 문서가 포함됩니다.
delete작업의 경우 이 줄은 생략됩니다. - 개행 구분자: 각 작업/메타데이터 쌍과 해당 소스(해당하는 경우)는 개행 문자(
\n)로 구분되어야 합니다. 전체 요청 본문은 개행 문자로 끝나야 합니다.
예제 구조:
{ "index": { "_index": "my-index", "_id": "1" } }
{ "field1": "value1" }
{ "delete": { "_index": "my-index", "_id": "2" } }
또는 삭제 작업의 경우:
curl -sS -H 'Content-Type: application/x-ndjson' \
-X POST 'http://localhost:9200/_bulk' \
--data-binary @bulk.ndjson
_bulk로 일반적인 작업 수행
_bulk API는 다재다능하며 단일 요청 내에서 여러 작업을 혼합하여 처리할 수 있습니다. 이것이 진정한 강점이며, 단일 왕복으로 복잡한 데이터 조작을 수행할 수 있습니다.
여러 문서 인덱싱
여러 문서를 인덱싱하려면 index 작업을 사용합니다. 지정된 ID의 문서가 이미 있으면 index가 덮어씁니다. 문서가 아직 존재하지 않는 경우에만 인덱싱되도록 하려면 대신 create 작업을 사용하세요.
예제: 두 개의 새 문서 인덱싱.
{ "index": { "_index": "my-index", "_id": "1" } }
{ "field1": "value1", "field2": "value2" }
{ "index": { "_index": "my-index", "_id": "2" } }
{ "field1": "another_value", "field2": "different_value" }
문서 업데이트
update 작업을 사용하여 문서를 업데이트할 수 있습니다. 업데이트할 문서 ID를 지정하고 변경하려는 필드가 있는 부분 문서를 제공합니다. 업데이트에 스크립트를 사용하려면 update 작업 내에서 수행할 수 있습니다.
예제: 기존 문서의 필드 업데이트.
{ "update": { "_index": "my-index", "_id": "1" } }
{ "doc": { "field1": "updated_value" } }
문서 삭제
문서를 삭제하려면 delete 작업을 사용하여 제거할 문서의 _index 및 _id를 지정합니다. 삭제 작업에는 소스 문서가 필요하지 않습니다.
예제: 문서 삭제.
{ "delete": { "_index": "my-index", "_id": "2" } }
작업 결합
실제 효율성은 이러한 작업을 혼합하는 데서 비롯됩니다. 동일한 _bulk 요청에서 새 문서를 인덱싱하고, 기존 문서를 업데이트하고, 다른 문서를 삭제할 수 있습니다.
예제: 하나의 요청에서 인덱싱, 업데이트 및 삭제.
{ "index": { "_index": "my-index", "_id": "3" } }
{ "field1": "new_document_field", "field2": "new_document_value" }
{ "update": { "_index": "my-index", "_id": "1" } }
{ "doc": { "field1": "further_updated_value" } }
{ "delete": { "_index": "my-index", "_id": "2" } }
응답 처리
_bulk API는 각 개별 작업의 결과를 자세히 설명하는 JSON 응답을 반환합니다. 이 응답을 구문 분석하여 모든 작업이 성공했는지 확인하고 오류를 식별하는 것이 중요합니다.
응답에는 items 배열이 포함되며, 각 요소는 요청의 작업 중 하나에 해당하며 동일한 순서로 표시됩니다. 각 항목에는 index, create, update 또는 delete 작업과 해당 상태(예: created, updated, deleted, noop) 및 기타 관련 메타데이터가 포함됩니다.
예제 응답 스니펫:
{
"took": 150,
"errors": false,
"items": [
{
"index": {
"_index": "my-index",
"_id": "3",
"version": 1,
"result": "created",
"_shards": {"total": 2, "successful": 1, "failed": 0},
"_seq_no": 0,
"_primary_term": 1
}
},
{
"update": {
"_index": "my-index",
"_id": "1",
"version": 2,
"result": "updated",
"_shards": {"total": 2, "successful": 1, "failed": 0},
"_seq_no": 1,
"_primary_term": 1
}
},
{
"delete": {
"_index": "my-index",
"_id": "2",
"version": 2,
"result": "deleted",
"_shards": {"total": 2, "successful": 1, "failed": 0},
"_seq_no": 2,
"_primary_term": 1
}
}
]
}
작업이 실패하면 응답의 최상위 errors 필드가 true가 되고 실패한 작업의 개별 항목에 문제를 설명하는 error 객체가 포함됩니다.
모범 사례 및 팁
- 배치 크기: 매우 큰 배치는 클라이언트 메모리, 조정 노드 및 데이터 노드에 부담을 줄 수 있습니다. 적당한 페이로드로 시작하고 처리량과 거부율을 측정한 다음 클러스터 및 문서 크기에 맞게 조정하세요.
- 오류 처리: 항상 응답에서 오류를 구문 분석하세요. 필요한 경우 일시적인 오류에 대한 재시도 로직을 구현하세요.
- 개행 구분자: 각 JSON 객체 사이에 개행 문자(
\n)가 올바르게 사용되었는지 확인하세요. 잘못된 형식은_bulkAPI 실패의 일반적인 원인입니다. - 병렬화: 매우 높은 수집 속도의 경우 여러
_bulk요청을 병렬로 보내는 것을 고려하되 클러스터의 용량을 염두에 두세요. createvs.index: ID가 이미 있는 경우 작업이 실패하도록 하려면create를 사용하세요. 기존 문서를 덮어써도 괜찮다면index를 사용하세요.- API 클라이언트: 대부분의 Elasticsearch 클라이언트 라이브러리는
_bulk요청을 구성하고 실행하는 편리한 방법을 제공하여 수동 형식 지정의 일부를 추상화합니다.
실용적인 요점
_bulk API는 요청 오버헤드를 줄이기 때문에 빠르지만, 클라이언트가 응답을 개별 결과 목록으로 처리할 때만 안전합니다. Content-Type: application/x-ndjson으로 유효한 NDJSON을 보내고, 클러스터가 흡수할 수 있는 크기로 배치를 유지하며, 일시적인 이유로 실패한 작업만 재시도하세요.