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)가 올바르게 사용되었는지 확인하세요. 잘못된 형식은 _bulk API 실패의 일반적인 원인입니다.
  • 병렬화: 매우 높은 수집 속도의 경우 여러 _bulk 요청을 병렬로 보내는 것을 고려하되 클러스터의 용량을 염두에 두세요.
  • create vs. index: ID가 이미 있는 경우 작업이 실패하도록 하려면 create를 사용하세요. 기존 문서를 덮어써도 괜찮다면 index를 사용하세요.
  • API 클라이언트: 대부분의 Elasticsearch 클라이언트 라이브러리는 _bulk 요청을 구성하고 실행하는 편리한 방법을 제공하여 수동 형식 지정의 일부를 추상화합니다.

실용적인 요점

_bulk API는 요청 오버헤드를 줄이기 때문에 빠르지만, 클라이언트가 응답을 개별 결과 목록으로 처리할 때만 안전합니다. Content-Type: application/x-ndjson으로 유효한 NDJSON을 보내고, 클러스터가 흡수할 수 있는 크기로 배치를 유지하며, 일시적인 이유로 실패한 작업만 재시도하세요.