ELK 공부 (3/3)

KIMAKUMA·2023년 4월 11일

ELK

목록 보기
3/7
post-thumbnail

Part 1

01. ElasticSearch 데이터 구조

1) 용어

  • Node: 클러스터에 포함된 단일 서버
  • Cluster: 동일한 클러스터 이름을 가지는 Node 집합
  • Index: 물리적인 Shard의 논리적인 단위, 색인 저장되는 문서의 저장 단위
  • Shard: 인덱스를 이루는 물리적인 문서들의 묶음 단위
  • Document: 색인 대상이 되는 문서의 기본적인 단위
  • Field: 문서를 구성하는 가장 최소 단위

2) Primary Shard와 Replica

정의

  • Primary Shard: 처음 생성된 Shard
  • Replica: Primary Shard를 복제한 Shard

특징

  • Primary Shard와 Replica는 서로 다른 Node에 저장됨
  • 시스템 다운, 네트워크 중단 등 문제 발생 시 Primary Shard를 가지고 있는 노드가 사라질 경우, Replica는가 Primary Shard가 되어 데이터 손실 없이 정상적으로 동작
  • Replica가 Primary Shard가 된 경우 그 Replica를 대체할 Replica를 다른 Node에 생성
  • Primary Shard는 처음 인덱스 생성시 지정하며 재색인 과정을 거쳐 변경 가능
  • Replica는 자유롭게 변경 가능

3) 마스터 노드와 데이터 노드

마스터 노드

  • 인덱스의 메타 데이터, 샤드의 위치와 같은 클러스터 상태 정보 관리
  • 클러스터 내에 단 하나만 존재
  • 장애에 대비하여 마스터 노드 후보들이 데이터를 공유하고 있는 상태이므로 선출 될 경우 바로 마스터 노드 역할 수행

데이터 노드

  • 실제로 색인된 데이터 저장

4) Split Brain

마스터 후보 또는 운영되고 있는 서버가 짝수인 경우, 네트워크 단절 등에 이유로 클러스터가 분리되어 데이터 저장 및 변경이 이루어지고 원 상태 복구 후 다시 하나의 클러스터로 병합하는 과정에서 데이터 정합성 문제가 발생되어 데이터 무결성이 유지되지 못하는 상황 또는 문제

  • Split Brain 방지를 위해서 마스터 후보 노드를 3개로 두고
    클러스터에 마스터 후보 노드가 최소 2개 이상 존재하고 있을 때에만
    클러스터가 동작하고 그렇지 않은 경우 클러스터는 동작을 멈추도록 해야 함

  • 최소 마스터 후보 개수: (전체 마스터 후보 노드 / 2) + 1

    • 6.x 버전 이전: yml 파일 설정
    • 7.x 버전 이후: 자동으로 설정 변경

Part 2

📢 아래부터는 Kibana 환경에서 작업한 내용입니다ㅏㅏㅏ

01. ElasticSearch 데이터 처리

1) REST API

  • PUT
    • 요청을 보낸 id의 데이터 변경
    • 요청한 id의 데이터가 없거나 _create로 작성한 경우 새로 저장
PUT index/_doc/1
{}

PUT index/_create/1
{}
  • GET
    • 요청한 id의 데이터를 JSON 형태로 반환
    • 쿼리를 통해 원하는 데이터만 조회 가능
GET index/_doc/1
{ query }

# 문서 갯수 조회
GET index/_count
{ query }
  • POST
    • 문서 id 없이 요청을 보낼 경우 자동으로 임의 id 형식으로 데이터 생성 후 저장
    • _update 요청을 통해 해당 id의 일부 필드만 수정
    • _update 요청 시 해당 id의 데이터가 없을 경우 새로 생성하여 저장
# 자동 id 생성 저장
POST index/_doc
{}

# 수정
POST index/_update/1
{}
  • DELETE
    • 요청한 id의 데이터 제거
    • 정상적으로 데이터가 삭제된 경우 "result" : "deleted" 결과 반환
    • 데이터가 삭제 되었지만 index가 남아있을 경우 "found" : false 반환
    • 데이터와 index 둘 다 삭제되었거나 처음부터 없었을 경우 "type" : "index_not_found_exception" , "status" : 404 반환
# 데이터
DELETE index/_doc/1

# Index
DELETE index

2) BULK

  • 여러 명령을 배치로 수행하기 위한 API
  • index, create, update, delete 동작이 가능
  • delete를 제외하고는 명령문과 데이터문을 한 줄씩 순서대로 입력
  • 별도의 파일에 벌크 명령어를 저장 후 실행 가능
# 쿼리 실행
POST _bulk
{ "index": { "_index": "test", "_id" :"1" } }
{ "field": "value one" }
{ "index": { "_index": "test", "_id": "2" } }
{ "field": "value two" }
{ "delete": { "_index": "test", "_id": "2" } }
{ "create": { "_index": "test", "_id": "3" } }
{ "field": "value three" }
{ "update": { "_index": "test", "_id": "1" } }
{ "doc": { "field": "value two" } }

# 명령어 파일 실행
$ curl -XPOST "http://localhost:9200/_bulk" -H 'Content-Type: application/json' --data-binary { filename }.json
  • URI 검색
    • 요청 주소 뒤에 q 파라미터를 통해 검색어를 입력하여 요청하는 방식
    • 루씬 기법 쿼리를 사용하여 쉽게 검색 가능
    • 웹브라우저 주소창 등에서 사용 가능
# 기본 형태
GET index/_search?q={ value }

# 필드 검색
GET index/_search?q={ field:value }
  • 데이터 본문 검색
    • 검색 쿼리를 데이터 본문으로 입력하는 방식
    • QueryDSL 사용하여 JSON 형식 쿼리
GET index/_search
{
	"qeury": {
		"match" : {
         	{ "field" }: { "value" }
		}
	}
}
  • 멀티 테넌시
    • 여러 개의 인덱스를 한 번에 묶어서 검색
    • 필드 구조가 변경되거나 크기가 커져서 샤드 설정을 변경하거나 할 때 용이
GET logs-2018-01,2018-02,2018-03/_search

GET logs-2018-*/_search

02. ElasticSearch 데이터 검색

  • Highlighting
    • 검색 결과의 하나 이상의 필드에서 강조 표시된 스니펫 반환
    • Highlighting을 요청하면 응답에는 highlight 강조 표시된 필드 및 강조 표시된 부분을 포함하는 각 검색 히트에 대한 추가 요소가 포함된다.
    • Highlighting이 표시되기 위해서는 실제 해당 필드가 존재해야 하며, 매핑 저장을 하지 않을 경우 _source에서 해당 필드를 뽑아 강조하여 반환해준다.
    • 설정
      • boundary_chars : 경계 문자 설정, Default .,!? \t\n
      • boundary_max_scan : 경계 문자 설정 거리, Default 20
      • boundary_scanner, boundary_scanner_locale, fragmenter, highlight_query 등
GET index/_search
{
  "query": {
    "match": { "content": "kimchy" }
  },
  "highlight": {
    "fields": {
      "content": {}
    }
  }
}
  • fields
    • 공통적으로 size을 통해 페이지 크기를 나누고 나눈 페이지를 이동하는 방법만 다르다.
    • 이동 방법으로는 from, search-after( + Point in Time), scroll API 등이 있다.
    • from 방식은 SQL에 offset과 같이 검색 결과에 몇 번째 데이터를 시작 위치 지정 후 시작 위치 부터 size 만큼 데이터 출력,
      첫 검색 결과를 스냅샷처럼 가지고 있는 것이 아닌기 때문에 중간에 인덱스 변경이 발생되면 검색 결과에 영향을 줄 수 있다.
      랜덤 엑세스이며 매번 검색마다 모든 데이터를 메모리에 올린 후 필터링을 하기 때문에 CPU와 Memory 사용 많아 비효울적이다.
    • search-after 방식은 live cursor 를 사용해서 정렬된 결과 중 특정 문서 다음부터 가져오는 방식이다.
      따로 context 를 저장하지 않는 stateless 방식이기 때문에 페이징 조회 도중에 인덱스에 update/delete/refresh 등 write 작업이 발생하면 정렬 결과에 영향을 줄 수 있다.
      정렬을 진행하기 때문에 랜덤 엑세스 불가
      검색 시점의 스냅샷과 비슷한 개념인 Point In Time (pit) 를 사용해서 이 영향을 최소화 할 수 있으나 7.12+ 이상 버전에서만 사용 가능
    • deep scrolling 에 적합하지만 context 유지 비용이 큼
      real time user request 엔 적합하지 않고 전체 dump / reindex 등에 사용
      stateful 방식
      검색이 시작된 시점에서 context 를 유지하는 stateful 방식이기 때문에, 중간에 데이터가 변경되어도 최초 검색 시점의 스냅샷 결과를 가져올 수 있음
      random access 불가
# Pagination(from)

# First request
GET products/_search
{
  "query": {
	"match": {
  	"name": "bike"
	}
  },
  "size": 10,
  "from": 0
}

# Next request
GET products/_search
{
  "query": {
	"match": {
  	"name": "bike"
	}
  },
  "size": 10,
  "from": 10
}

# Search after

# First request
GET products/_search
{
  "query": {
	"match": {
  	"name": "bike"
	}
  },
  "size": 10,
  "sort": [
	{
  	"_score": "desc"
	},
	{
  	"id.keyword": "asc"
	}
  ]
}

# Next request
GET products/_search
{
  "query": {
	"match": {
  	"name": "bike"
	}
  },
  "size": 10,
  "sort": [
	{
  	"_score": "desc"
	},
	{
  	"id.keyword": "asc"
	}
  ],
  "search_after": [
	0.2876821,
	"1"
  ]
}

# Create PIT for index
POST products/_pit?keep_alive=2m

# First page
GET _search
{
  "from": 0,
  "size": 10,
  "query": {
	"match": {
  	"name": "bike"
	}
  },
  "pit": {
	"id": "85ezAwEIcHJvZHVjdHMWSzJZVTdKOU1RLU9SRVBsck43SGg3dwAWS3ptRzhJX3FUZE9iaGVpY3J5VmhTdwAAAAAAAAAABxZVYm5aNWF2U1NqcWJJdXhPc1dyS2hBAAEWSzJZVTdKOU1RLU9SRVBsck43SGg3dwAA",
	"keep_alive" : "2m"
  }
}

# Following page
GET _search
{
  "from": 10,
  "size": 10,
  "query": {
	"match": {
  	"name": "bike"
	}
  },
  "pit": {
	"id": "85ezAwEIcHJvZHVjdHMWSzJZVTdKOU1RLU9SRVBsck43SGg3dwAWS3ptRzhJX3FUZE9iaGVpY3J5VmhTdwAAAAAAAAAABxZVYm5aNWF2U1NqcWJJdXhPc1dyS2hBAAEWSzJZVTdKOU1RLU9SRVBsck43SGg3dwAA",
	"keep_alive" : "2m"
  }
}

# First request
GET products/_search?scroll=1m
{
  "size": 10,
  "query": {
	"match": {
  	"name": "bike"
	}
  }
}

# Next request
GET _search/scroll
{
  "scroll": "1m",
  "scroll_id": "FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFlViblo1YXZTU2pxYkl1eE9zV3JLaEEAAAAAAAAAChZLem1HOElfcVRkT2JoZWljcnlWaFN3"
}

03. ElasticSearch Query DSL

04. ElasticSearch 데이터 색인과 데이터 분석

05. ElasticSearch 인덱스 설정과 매핑

06. ElasticSearch Aggregataion

동기님의 정리글을 인용했습니다~ 감사요~

0개의 댓글