├── README.md └── pictures ├── .DS_Store ├── analysis-chain.png ├── close-api.png ├── doc-search.png ├── elk_stack.png ├── es-cluster-structure1.png ├── es-cluster-structure2.png ├── es-data-structure.png ├── index-writing.png ├── inverted_index.png ├── master-fault.png ├── option-by-license.png ├── remove-multipath01.png ├── remove-multipath02.png ├── remove-multipath03.png ├── rolling-restart01.png ├── rolling-restart02.png ├── rolling-restart03.png ├── rolling-restart04.png ├── search_fetch.png ├── search_query.png ├── shard-1.png ├── shard-2.png ├── shard-3.png ├── shard-4.png ├── shard-allocation.png ├── split-brain.png ├── term-index.png ├── term-type.png └── type-deprecated.png /README.md: -------------------------------------------------------------------------------- 1 | elasticsearch 이론 정리중 2 | 3 |

4 | 5 | ### Part 1. Elasticsearch 시작하기 6 | 7 | - [**Elasticsearch 기본 개념**](https://github.com/itmare/es_lecture#part-1-elasticsearch-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-1) 8 | 9 | - [Elasticsearch에 대하여](https://github.com/itmare/es_lecture#elasticsearch%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC) 10 | - [Elasticsearch의 용어 및 개념 정리](https://github.com/itmare/es_lecture#elasticsearch-%EC%9A%A9%EC%96%B4-%EB%B0%8F-%EA%B0%9C%EB%85%90%EC%A0%95%EB%A6%AC) 11 | 12 | - [**Elasticsearch 설치**](https://github.com/itmare/es#elasticsearch-%EC%84%A4%EC%B9%98) 13 | 14 | - [repo 등록 설치](https://github.com/itmare/es#1-repo-%EB%93%B1%EB%A1%9D-%EC%84%A4%EC%B9%98) 15 | - [RPM으로 설치](https://github.com/itmare/es#2-rpm%EC%9C%BC%EB%A1%9C-%EC%84%A4%EC%B9%98) 16 | - [zip, tar로 설치](https://github.com/itmare/es#3-zip-tar%EB%A1%9C-%EC%84%A4%EC%B9%98) 17 | 18 | - [**Elasticsearch 기본 동작**](https://github.com/itmare/es_lecture#elasticsearch-%EA%B8%B0%EB%B3%B8-%EB%8F%99%EC%9E%91) 19 | 20 | - [인덱스 생성 및 삭제, 조회](https://github.com/itmare/es_lecture#%EC%9D%B8%EB%8D%B1%EC%8A%A4-%EC%83%9D%EC%84%B1-%EB%B0%8F-%EC%82%AD%EC%A0%9C-%EC%A1%B0%ED%9A%8C) 21 | - [문서 색인 및 조회](https://github.com/itmare/es_lecture#%EB%AC%B8%EC%84%9C-%EC%83%89%EC%9D%B8-%EB%B0%8F-%EC%A1%B0%ED%9A%8C) 22 | - [문서 갱신 및 삭제](https://github.com/itmare/es#%EB%AC%B8%EC%84%9C-%EA%B0%B1%EC%8B%A0-%EB%B0%8F-%EC%82%AD%EC%A0%9C) 23 | 24 | - [**Elasticsearch 플러그인**](https://github.com/itmare/es_lecture#elasticsearch-%ED%94%84%EB%9F%AC%EA%B7%B8%EC%9D%B8) 25 | 26 | - 플러그인이란? 27 | - 플러그인의 설치 28 | - [한눈에 클러스터를 보기 위한 head 플러그인 활용](https://github.com/itmare/es#elasticsearch-head) 29 | - [클러스터의 사용률을 보기 위한 HQ 플러그인 활용](https://github.com/itmare/es#elasticsearch-hq) 30 | 31 |
32 | 33 | ### Part 2. Elasticsearch Basic Usage 34 | 35 | - [**Elasticsearch 환경 설정**](https://github.com/itmare/es_lecture#elasticsearch-%ED%99%98%EA%B2%BD%EC%84%A4%EC%A0%95) 36 | 37 | - [Elasticsearch의 핵심인 elasticsearch.yml 설정](https://github.com/itmare/es_lecture#1-static-settings-elasticsearchyml) 38 | - [힙사이즈의 중요성, jvm.options](https://github.com/itmare/es_lecture#2-static-settings-jvmoptions) 39 | - [로그를 어떻게 모을 것인지 설정하는 log4j2.properties](https://github.com/itmare/es_lecture#3-static-settings-log4j2properties) 40 | 41 | - **Elasticsearch 클러스터 운영** 42 | 43 | - [무중단 운영을 위한 rolling restart](https://github.com/itmare/es_lecture#rolling-restart) 44 | - [안정적인 성능 제공을 위한 샤드 분배 방법](https://github.com/itmare/es_lecture#shard-allocation) 45 | - [index setting](https://github.com/itmare/es_lecture#index-setting) 46 | - [미리 정의된 template으로 인덱싱하기](https://github.com/itmare/es_lecture#template) 47 | - [비용을 절감하는 운영 방법 hot-warm data node](https://github.com/itmare/es_lecture#hot-warm-data-node) 48 | 49 | - **Elasticsearch API 활용하기** 50 | 51 | - [클러스터 운영 \_cluster API](https://github.com/itmare/es_lecture#cluster-api---%ED%81%B4%EB%9F%AC%EC%8A%A4%ED%84%B0-%EC%9A%B4%EC%98%81-api-%EB%8B%A4%EB%A3%A8%EA%B8%B0) 52 | - [클러스터 인덱스 마이그레이션 \_reindex API](https://github.com/itmare/es_lecture#reindex-api---%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%A7%88%EC%9D%B4%EA%B7%B8%EB%A0%88%EC%9D%B4%EC%85%98) 53 | - [벌크 인덱싱 \_bulk API](https://github.com/itmare/es_lecture#bulk-api---%EB%8F%84%ED%81%90%EB%A8%BC%ED%8A%B8-%ED%95%9C%EB%B2%88%EC%97%90-%EC%9D%B8%EB%8D%B1%EC%8B%B1%ED%95%98%EA%B8%B0) 54 | - [그 외 운영에 유용한 APIs](https://github.com/itmare/es_lecture#%EA%B7%B8-%EC%99%B8-%EC%9A%B4%EC%98%81%EC%97%90-%EC%9C%A0%EC%9A%A9%ED%95%9C-api) 55 | 56 |
57 | 58 | ### Part 3. Elasticsearch Advanced Usage 59 | 60 | - [**검색엔진으로 Elasticsearch 활용하기**](https://github.com/itmare/es_lecture#%EA%B2%80%EC%83%89%EC%97%94%EC%A7%84%EC%9C%BC%EB%A1%9C-elasticsearch-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0) 61 | 62 | - [인덱스 생성 과정](https://github.com/itmare/es_lecture#%EC%9D%B8%EB%8D%B1%EC%8A%A4-%EC%83%9D%EC%84%B1-%EA%B3%BC%EC%A0%95) 63 | - [분석기 변경 방법](https://github.com/itmare/es_lecture#%EB%B6%84%EC%84%9D%EA%B8%B0-%EB%B3%80%EA%B2%BD-%EB%B0%A9%EB%B2%95) 64 | - [쿼리 생성](https://github.com/itmare/es_lecture#%EC%BF%BC%EB%A6%AC-%EC%83%9D%EC%84%B1) 65 | 66 | - [**Elasticsearch 색인 기능 최적화**](https://github.com/itmare/es_lecture#elasticsearch-%EC%83%89%EC%9D%B8-%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94) 67 | 68 | - [필요하지 않다면 쓰지 말아야 할 기능들, \_all 필드](https://github.com/itmare/es_lecture#%ED%95%84%EC%9A%94%ED%95%98%EC%A7%80-%EC%95%8A%EB%8B%A4%EB%A9%B4-%EC%93%B0%EC%A7%80-%EB%A7%90%EC%95%84%EC%95%BC-%ED%95%A0-%EA%B8%B0%EB%8A%A5%EB%93%A4-_all-%ED%95%84%EB%93%9C) 69 | - [미리 정해놓은 스키마로 리소스를 절약할 수 있는 static mapping 적용하기](https://github.com/itmare/es_lecture#%EB%AF%B8%EB%A6%AC-%EC%A0%95%ED%95%B4%EB%86%93%EC%9D%80-%EC%8A%A4%ED%82%A4%EB%A7%88%EB%A1%9C-%EB%A6%AC%EC%86%8C%EC%8A%A4%EB%A5%BC-%EC%A0%88%EC%95%BD%ED%95%A0-%EC%88%98-%EC%9E%88%EB%8A%94-static-mapping-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0) 70 | - [인덱싱 된 데이터를 검색 결과에 반영할 수 있도록 refresh_interval 변경하기](https://github.com/itmare/es_lecture#%EC%9D%B8%EB%8D%B1%EC%8B%B1-%EB%90%9C-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A5%BC-%EA%B2%80%EC%83%89-%EA%B2%B0%EA%B3%BC%EC%97%90-%EB%B0%98%EC%98%81%ED%95%A0-%EC%88%98-%EC%9E%88%EB%8F%84%EB%A1%9D-refresh_interval-%EB%B3%80%EA%B2%BD%ED%95%98%EA%B8%B0) 71 | 72 | - [**Elasticsearch 검색 성능 최적화**](https://github.com/itmare/es_lecture#elasticsearch-%EA%B2%80%EC%83%89-%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94) 73 | 74 | - [쿼리 튜닝 하기: 검색에 유리한 튜닝방법](https://github.com/itmare/es_lecture#%EC%BF%BC%EB%A6%AC-%ED%8A%9C%EB%8B%9D-%ED%95%98%EA%B8%B0-%EA%B2%80%EC%83%89%EC%97%90-%EC%9C%A0%EB%A6%AC%ED%95%9C-%ED%8A%9C%EB%8B%9D%EB%B0%A9%EB%B2%95) 75 | - [샤드 배치 결정하기: 검색 성능을 위해 샤드 배치를 결정하는 노하우](https://github.com/itmare/es_lecture#%EC%83%A4%EB%93%9C-%EB%B0%B0%EC%B9%98-%EA%B2%B0%EC%A0%95%ED%95%98%EA%B8%B0-%EA%B2%80%EC%83%89%EC%84%B1%EB%8A%A5%EC%9D%84-%EC%9C%84%ED%95%B4-%EC%83%A4%EB%93%9C%EB%A5%BC-%EB%B0%B0%EC%B9%98%ED%95%98%EB%8A%94-%EB%85%B8%ED%95%98%EC%9A%B0) 76 | 77 | - [**Elasticsearch 모니터링**](https://github.com/itmare/es_lecture#elasticsearch-%EB%AA%A8%EB%8B%88%ED%84%B0%EB%A7%81) 78 | 79 | - [rejected, 데이터의 누락이 발생하는 순간](https://github.com/itmare/es_lecture#rejected-%EB%8D%B0%EC%9D%B4%ED%84%B0%EC%9D%98-%EB%88%84%EB%9D%BD%EC%9D%B4-%EB%B0%9C%EC%83%9D%ED%95%98%EB%8A%94-%EC%88%9C%EA%B0%84) 80 | - [\_cat API로 클러스터 상태 모니터링 하기](https://github.com/itmare/es_lecture#_cat-api%EB%A1%9C-%ED%81%B4%EB%9F%AC%EC%8A%A4%ED%84%B0-%EC%83%81%ED%83%9C-%EB%AA%A8%EB%8B%88%ED%84%B0%EB%A7%81-%ED%95%98%EA%B8%B0) 81 | - [\_stats, \_nodes API로 클러스터의 리소스 사용 지표 모니터링 하기](https://github.com/itmare/es_lecture#_stats-_nodes-api%EB%A1%9C-%ED%81%B4%EB%9F%AC%EC%8A%A4%ED%84%B0%EC%9D%98-%EB%A6%AC%EC%86%8C%EC%8A%A4-%EC%82%AC%EC%9A%A9-%EC%A7%80%ED%91%9C-%EB%AA%A8%EB%8B%88%ED%84%B0%EB%A7%81-%ED%95%98%EA%B8%B0) 82 | 83 | - **Elasticsearch 성능 테스트** 84 | 85 | - [성능 테스트 시나리오](https://github.com/itmare/es_lecture#%EC%84%B1%EB%8A%A5-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%8B%9C%EB%82%98%EB%A6%AC%EC%98%A4) 86 | - [성능 테스트 환경](https://github.com/itmare/es_lecture#%EC%84%B1%EB%8A%A5-%ED%85%8C%EC%8A%A4%ED%8A%B8-%ED%99%98%EA%B2%BD) 87 | - [성능 테스트 결과 해석](https://github.com/itmare/es_lecture#%EC%84%B1%EB%8A%A5-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EA%B2%B0%EA%B3%BC-%ED%95%B4%EC%84%9D) 88 | 89 |





90 | 91 | --- 92 | 93 | Part 1. Elasticsearch 시작하기 94 | ============================== 95 | 96 | --- 97 | 98 |

99 | 100 | Elasticsearch 기본 개념 101 | ======================= 102 | 103 |

104 | 105 | ### Elasticsearch에 대하여 106 | 107 | - Elasticsearch: 고가용성의 확장 가능한 오픈소스 108 | - 자료 쌓아두고 필요한 자료를 빠르게 검색할 수 있도록 해주는 도구 109 | - RESTful방식의 Native API를 제공하고 다양한 프로그래밍 언어를 위한 API도 제공 110 | - Native API의 장단점 111 | - 장점: 쉽게 사용 가능하다. 112 | - 단점: Json형태의 검색문을 직접 작성해야 한다. 113 | 114 | ##### 1. Full-text 검색엔진으로서의 ES 115 | 116 | - 루씬(Lucene) 117 | 118 | - apache software재단의 검색엔진 상위 프로젝트 119 | - java언어로 이루어진 정보 검색 라이브러리 120 | - free open-source software, Doug Cutting에 의해 개발 121 | - apache license하에 배포 122 | 123 | - 단독 서비스 124 | 125 | - ES는 Shay banon이 Lucene기반으로 만든 검색엔진 126 | 127 | - apache 2.0 license에 의거 128 | 129 | - HTTP Web Interface와 Schema에 자유로운 Json형태의 도큐먼트 지원 130 | 131 | - 준 실시간 분산형 검색엔진 132 | 133 | ##### 2. 분석엔진으로서의 ES 134 | 135 | - 검색엔진으로서의 ES에, 몇가지 솔수션을 추가해 분석엔진으로 활용 136 | - semi-realtime 분석 엔진으로 사용 가능 137 | - beats: log나 data의 원본을 elasticsearch 로 전달 138 | - Logstash: 직접 log를 전달하거나 beats에서 데이터 전달받아 파싱이나 필터링하여 es에 전달 139 | - kibana: es에 수집된 데이터를 통계/집계 내어 시각화 140 | 141 | 142 | 143 |

144 | 145 | ### Elasticsearch 용어 및 개념정리 146 | 147 | #### Json 148 | 149 | - 사람이 읽고 쓰기 쉬운 형태의 경량 데이터 구조 150 | - Key:Value의 쌍으로 사용 151 | - Value에는 Key:Value형태의 object나 list도 들어갈 수 있음 152 | 153 |

154 | 155 | #### cluster 156 | 157 | - es는 클러스터로 구성, 클러스터는 하나 이상의 노드로 구성 158 | - 사용자는 클러스터를 통해 데이터를 밀어넣고 검색요청 한다. 159 | - 클러스터는 고유의 cluster_name과 cluster_uuid를 갖고 운영된다. 160 | 161 |

162 | 163 | #### node 164 | 165 | - 노드는 클러스터를 구성하는 es프로세스 166 | - 서로 헬스 체크를 하거나, 실제 데이터가 인덱싱 되어 적재 167 | - 클라이언트의 검색 요청에 의해 데이터를 리턴 168 | - 노드는 각자의 node_name과 node_uuid를 갖는다. 169 | - 역할에 따라 여러가지 노드로 사용 170 | 171 | - master node 172 | 173 | - 클러스터 구성의 기준 174 | - 구성 노드들의 헬스 체크를 담당 175 | 176 | - data node 177 | 178 | - 실제 데이터가 적재되고 클라이언트의 요청에 데이터 리턴을 담당 179 | 180 | - all node 181 | 182 | - master와 data의 구분이 필요없을때, 두가지 역할을 전부 담당 183 | - 확장이 거의 필요없고 비용 절감을 위해 사용 184 | 185 | - client node 186 | 187 | - 쿼리만을 받기 위한 노드 188 | - master,data,all node들이 쿼리를 받을 수 있기 때문에 부하 분산용으로 쓰임 189 | 190 | - ingest node 191 | 192 | - 인덱싱할때 데이터의 전처리를 위한 노드 193 | 194 |

195 | 196 | #### Index 197 | 198 | - 199 | - 도큐먼트들의 모음 200 | - RDB의 데이터베이스와 비슷한 개념 201 | - 여러 도큐먼트들이 하나의 인덱스에 적재 202 | - 사전에 정의되어야 할 데이터의 타입이나 특정한 구조가 필용하지 않다면 최초 데이터가 들어올때 자동 생성된다. 203 | 204 |

205 | 206 | #### Type 207 | 208 | - 209 | - 타입은 인덱스의 파티션으로 사용 210 | - RDB의 테이블과 비슷한 개념 211 | - 하나의 인덱스에 도큐먼트를 넣을 때 타입을 분리해서 인덱싱 가능 212 | - 하나의 인덱스에 단일 타입 권고 (\_doc) 213 | - es 6.x부터 천천히 deprecated (6.0: 매핑 타입 삭제, 7.0: 완전 타입 삭제) 214 | - 루신엔진 특성상 인덱스(DB)에 여러개의 타입이 들어가 있어도 모든 매핑 정보가 생성되어 저장되어진다. 215 | - 완전 상이한 데이터가 들어 갈 경우 광장히 비효적일 수 밖에 없다. 216 | - 따라서 여러개의 타입이 들어가더라도 내부적으론 같기 때문에 타입을 삭제하기로  217 | - [(참고1: removal of mappings)](https://www.elastic.co/guide/en/elasticsearch/reference/master/removal-of-types.html) 218 | - [(참고2: what is type and why they decided type will be deprecated)](https://medium.com/@federicopanini/elasticsearch-6-0-removal-of-mapping-types-526a67ff772) 219 | 220 |

221 | 222 | #### Document 223 | 224 | - es 저장 기본단위 225 | - RDB의 columns나 rows와 비슷한 개념 226 | - 도큐먼트는 데이터로 적재될 때 Document ID를 갖는다. 227 | - Doc ID는 기본적으로 랜덤하게 생성되지만, 필요에 의해 사용자 정의된 값으로도 생성 가능 228 | - Doc ID는 데이터를 찾아가는 메타데이터라 보면 된다. 229 | 230 |

231 | 232 | #### Shard 233 | 234 | - 인덱스의 데이터를 나누는 단위 235 | - 무한정 데이터를 인덱스에 넣다보면 문제 발생 236 | - 단일 노드의 디스크 볼륨 크기의 유한성으로 더 이상 저장 불가 상황이 오게 됨 237 | - 단일 노드의 유한한 CPU, 혹은 memory자원으로 indexing이나 searching의 성능 저하 238 | - 이런 문제 해결위해, ES에 도입된 개념이 샤딩 239 | - 인덱스에 들어오는 도큐멘트들을 관계형 데이터베이스처럼 컬럼별로 나누는 vertical이 아닌, 문서별로 횡(horizontal)으로 나눠 샤드에 저장 240 | - primary shard 241 | - 인덱싱되어 들어온 도큐먼트의 원본 샤드 242 | - es에 도큐먼트가 인덱싱 될 때, 가장 처음 생성되는 샤드 243 | - 샤드에는 넘버가 있어 몇 번째 샤드인지 식별 가능 244 | - 한번 지정한 샤드 갯수는 불변 245 | - ES 6.x기준, 별도 설정하지 않으면 5개의 primary shard가 default (7.x부터 1로 변경 예정) 246 | - replica shard 247 | - primary shard의 복제샤드를 의미 248 | - primary shard 인덱싱 후, 복제 시작 249 | - replica shard에 넘버링 하여 어떤 primary shard의 복제본인지 식별 가능 250 | - 별도 설정하지 않으면 1개의 replica shard가 default 251 | - 각 es shard는 Lucene 인덱스 252 | - 단일 Lucene 인덱스가 포함할 수 있는 문서 수의 최대 한도가 2,147,483,519건 253 | - replica shard가 있기 때문에 샤드/노드 오류가 발생하더라도 es클러스터 고가용성이 유지된다. 254 | - 모든 replica shard에서 병렬 방식으로 검색을 실행할 수 있으므로 검색 처리량 확장 가능 255 | - 단점: 인덱싱 할 때 primary샤드의 복제를 하는 과정이 추가되기 때문에 256 | 1. I/O가 두배로 발생하기 때문에 인덱싱 성능 저하 257 | 2. 디스크 볼륨도 실제 도큐먼트의 두배 필요 258 | 259 | 260 | 261 | - 싱글 노드에 3개의 샤드로 클러스터 구성 262 | - 시간 지날수록, 문서는 점점 늘어난다. 결국 싱글노드의 허용 볼륨 모두 소진 263 | - 클러스터에 더 이상 데이터 적재 불가 264 | 265 | 266 | 267 | - 동일한 설정의 노드 한대 추가 268 | - es클러스터가 일정 샤드들을 새로 투입된 노드로 분배 269 | - 두대의 노드가 인덱싱 및 검색 응답에 참여 270 | 271 | 272 | 273 | - 노드가 한대 fail날 경우, 데이터의 안정성 보장 불가 274 | - 복제본인 replica shard 추가 275 | 276 | 277 | 278 | - 노드 한대 fail시, 남아있는 나머지 노드들의 replica shard가 primary shard로 승격됨 279 | - fail된 노드의 replica shard는 남아있는 나머지 노드들의 primary shard를 재복제하여 replica shard를 만듦 280 | 281 |

282 | 283 | #### Segment 284 | 285 | - 샤드는 다시 세그먼트로 나눠짐 286 | - 도큐먼트가 인덱싱될 때, 그 데이터가 시스템 버퍼 캐시 영역으로 적재됨 287 | - 이후, 데이터를 디스크의 세그먼트에 기록 288 | - 이 과정에서 refresh를 거쳐야 commit point를 생성하여 검색 가능한 상태로 전환 289 | 290 |

291 | 292 | #### es 구성 293 | 294 | - physical 구성 295 | - cluster > Node > Indice > Shard 296 | - logical 구성 297 | - Index > Type > Document > field:value 298 | 299 |

300 | 301 | #### es 데이터 구조 302 | 303 | 304 | 305 | - 각각의 샤드는 루씬 인덱스 306 | 307 |

308 | 309 | #### RDBMS와 비교 310 | 311 | | RDBMS | Elasticsearch | 312 | |:--------:|:-------------:| 313 | | schema | mapping | 314 | | database | index | 315 | | table | type | 316 | | row | document | 317 | | column | field | 318 | 319 |

320 | 321 | #### es 클러스터 구조 322 | 323 | ##### Cluster > node > index > type > document 324 | 325 | ###### - 예시1 326 | 327 | 328 | 329 |

330 | 331 | ###### - 예시2 332 | 333 | 334 | 335 | | 이름 | 개수 | 336 | |:--------:|:----:| 337 | | index | 1 | 338 | | instance | 3 | 339 | | shard | 4 | 340 | | replica | 2 | 341 | 342 | - es는 클러스터 구조로 구성되어 있으며 샤드와 복제본의 수 설정에 따라 각 노드에 스스로 샤드를 분배하여 장애 발생 시, 데이터 손실을 최소화 343 | 344 |




345 | 346 |

347 | 348 | Elasticsearch 기본 동작 349 | ======================= 350 | 351 |

352 | 353 | 인덱스 생성 및 삭제, 조회 354 | ------------------------- 355 | 356 | - 기본사용 되는 커맨드 357 | 358 | ```shell 359 | # 모든 default 설정과 함께 twitter index가 생성된다. 360 | PUT twitter 361 | ``` 362 | 363 | #### 인덱스 생성 3가지 방법 364 | 365 | ##### 1. 인덱스의 "settings"를 정의 366 | 367 | 1. static index settings 368 | - number_of_shards : primary 샤드 갯수 설정 369 | 2. Dynamic index settings 370 | 371 | - number_of_replicas : replica 샤드 갯수 설정 372 | - refresh_interval : 검색 commit point를 만드는 refresh interval 설정 373 | - cluster.routing.allocation.enable : 인덱스의 샤드들의 라우팅 허용 설정 374 | 375 | ```java 376 | // ex) 377 | PUT twitter 378 | { 379 | "settings" : { 380 | "index" : { 381 | "number_of_shards" : 3, 382 | "number_of_replicas" : 2 383 | } 384 | } 385 | } 386 | 387 | // 간단하게 388 | PUT twitter 389 | { 390 | "settings" : { 391 | "number_of_shards" : 3, 392 | "number_of_replicas" : 2 393 | } 394 | } 395 | ``` 396 | 397 | ##### 2. 인덱스의 mappings를 정의 398 | 399 | ```java 400 | // ex) 401 | PUT test 402 | { 403 | "settings" : { 404 | "number_of_shards" : 1 405 | }, 406 | "mappings" : { 407 | "_doc" : { 408 | "properties" : { 409 | "field1" : { "type" : "text" } 410 | } 411 | } 412 | } 413 | } 414 | ``` 415 | 416 | ##### 3. 사용자 정의된 도큐먼트를 인덱싱 417 | 418 | - alias등 사용 가능 419 | 420 |

421 | 422 | 문서 색인 및 조회 423 | ----------------- 424 | 425 | - 한번 설정한 샤드 갯수는 변경 불가 426 | - 문서는 인덱싱 될때 랜덤한 string을 doc id로 할당받거나, 사용자가 정의한 doc id로 생성됨 427 | - 사용자는 생성된 doc id를 통해 문서를 가져올 수 있음 428 | - 프라이머리 샤드가 항상 먼저 writing된다. 429 | - 프라이머리 샤드의 writing이 전부 완료된 후, 리플리카 샤드로 복제를 시작한다. 430 | 431 |
432 | 433 | #### 문서 인덱싱 434 | 435 | 436 | 437 | - 인덱스 쓰기

438 | 439 | #### 문서 조회 440 | 441 | 442 | 443 | - 조회 요청을 round robin으로 처리 444 | - 최초 요청받은 노드가 응답 주면 좋겠지만, 445 | - 데이터를 가진 NODE1이 계속 요청을 클라이언트에게 리턴 446 | - 문서를 가진 다른 노드는 상대적으로 계속 유휴해지는 단점 447 | - 요청 자체도 앞단에서 balancing 권고 448 | 449 |

450 | 451 | Elasticsearch 프러그인 452 | ---------------------- 453 | 454 | Core Plugins 455 | 456 | - Elasticsearch 에서 공식적으로 지원하는 플러그인 457 | - ES 버전이 올라갈 때마다 같이 버전 업데이트가 지원되고 사용권고 458 | 459 | Community contributed 460 | 461 | - 개인 개발자나 회사에 의해 지원되는 플러그인 462 | 463 | ##### 대표적으로 elasticsearch-head, elasticsearch-HQ 464 | 465 |




466 | 467 | --- 468 | 469 | Part 2. Elasticsearch Basic Usage 470 | ================================= 471 | 472 | --- 473 | 474 |

475 | 476 | elasticsearch 환경설정 477 | ====================== 478 | 479 | ### 1. static settings: elasticsearch.yml 480 | 481 | - elasticsearch의 핵심 설정 482 | - 노드 별로 설정파일에 설정 483 | 484 |
485 | 486 | - `cluster.name` 487 | - 클러스터 식별 이름 설정 488 | - `node.name` 489 | - 노드 식별 이름 설정 490 | - `path.data` 491 | 492 | - index 데이터 저장할 경로 설정 (싱글, 멀티 가능) 493 | - path.data: /data1 494 | - path.data: /data1,/data2 495 | - 멀티패스 경우, 샤드 계획 수립이 중요!!! 496 | 497 | - `path.logs` 498 | 499 | - es 로그 저장 경로 설정 500 | - app 운영 로그, es deprecated 로그, index로그, searching slow 로그 501 | 502 | - `Discovery` 503 | 504 | - 노드가 시작될 때 클러스터링의 기준이 되는 master노드를 찾아가는 과정 505 | - EC2, Azure, GCE등도 지원(플러그인 필요) 506 | - ping을 기반으로 동작 507 | 508 | - `discovery.zen.ping.unicast.hosts` 509 | 510 | - 동일한 클러스터 이름을 전제로 설정된 호스트 가운데 master가 결정됨 511 | - master노드가 있으면 클러스터에 합류 512 | - master가 없으면 지정된 호스트 중 하나가 master로 선출 513 | 514 | - `discovery.zen.minimum_master_nodes` 515 | 516 | - 최소 마스터 갯수 설정 517 | - (마스터노드 갯수 / 2) + 1 개 설정 518 | - 해당 노드 갯수만큼 마스터가 내려가면 데이터 무결성을 위해 클러스터 중지 519 | 520 |
521 | 522 | - Split Brain이란? 523 | 524 | - 마스터 후보 노드(master eligible node) 사이에 네트워크가 단절 됐을 때, 각각의 마스터 후보 노드가 마스터로 승격되어 두개의 클러스터로 동작하는 현상 525 | - 클러스터 구성에서 네트워크 단절로 인해 여러개의 노드가 서로 마스터로 인식되는 증상 526 | - 4개의 마스터를 운영할 때에는 최소 마스터 갯수를 4/2 + 1 = 3으로 설정 527 | - 2대가 내려가는 순간 클러스터를 중지시켜 split brain을 방지 528 | 529 | 530 | 531 | 1. 마스터 노드와 후보노드 M1과 M2,3,4를 가지고 있는 클러스터A 532 | 2. 네트워크 단절, 각 부분에서 마스터 후보 노드가 마스터로 승격, 두개의 클러스터로 동작 533 | 3. 네트워크 복구 되어도 데이터 비동기 문제로 인해 데이터의 손실 없이는 클러스터 복구가 불가능 534 | 535 |
536 | 537 | - 마스터 fault 538 | 539 | - 마스터로 정의된 노드들은 각각 cluster state version을 갖고 있음 540 | - version은 클러스터에 합류한 순서, "가장 먼저 들어온 노드가 가장 클러스터의 상태를 잘 알고 있는 노드다"라는 전제 541 | - 실제 마스터가 내려가면 각각의 마스터 노드들은 zen discovery에 정의된 호스트에게 ping 체크를 시작 542 | - 응답이 오는 호스트 중 cluster state version이 가장 낮은 호스트를 마스터로 선출 543 | 544 | 545 | 546 |
547 | 548 | ##### Network 설정 549 | 550 | - `network.host` 551 | - 노드가 응답을 할 수 있는 아이피나 호스트를 설정 (`bind.host + publish_host`\) 552 | - `network.bind.host` 553 | - network.host 설정에서 외부의 데이터 호출을 받는 부분만 분리 554 | - `network.publish_host` 555 | - 클러스터 내의 다른 노드들과 통신을 하는 부분만 분리 556 | - `http.port` 557 | - http프로토콜을 통해 elasticsearch의 API를 전달할 때 사용할 포트 설정 558 | - `transport.tcp.port` 559 | - 클러스터 내에 노드들이 서로 통신을 할 때 사용할 포트 설정 560 | - 노드는 서로의 용량이나 샤드의 상태를 알아야하기 때문에 tcp 통신을 해야한다. 561 | 562 | ##### Node Roles 설정 563 | 564 | - Master-eligible Node 565 | 566 | - 마스터 노드로서의 역할을 할 수 있는 role이 부여된 노드 567 | 568 | ```shell 569 | node.master: true 570 | node.data: false 571 | node.ingest: false 572 | ``` 573 | 574 | - Data Node 575 | 576 | - 데이터가 저장되는 역할을 할 수 있는 role이 부여된 노드 577 | 578 | ```shell 579 | node.master: false 580 | node.data: true 581 | node.ingest: false 582 | ``` 583 | 584 | - Ingest Node 585 | 586 | - 문서가 인덱싱 되기 전에 파이프라인을 통해 사전처리를 할 수 있는 role이 부여된 노드 (default: true) 587 | - 즉, 문서가 인덱싱 되기 전에 어떤 기준에 의해 파싱해서 데이터가 들어오고, 그것들을 사전 처리해서 데이터 노드에게 넘겨주는 역할 588 | - indexing 전에, processor를 순서대로 나열한 pipeline을 정의한다. [processor list](https://www.elastic.co/guide/en/elasticsearch/reference/current/ingest-processors.html) 589 | 590 | ```shell 591 | node.master: false 592 | node.data: false 593 | node.ingest: true 594 | ``` 595 | 596 | - Coordinate Node 597 | 598 | - 클라이언트의 요청을 받고 라우팅 및 분산만 처리할 수 있는 role이 부여된 노드 599 | 600 | ```shell 601 | node.master: false 602 | node.data: false 603 | node.ingest: false 604 | ``` 605 | 606 | - `http.cors.enabled: true` 607 | 608 | - 웹 브라우저에서 elasticsearch에 접근할 수 있도록 해주는 설정 609 | - Head나 HQ 플러그인을 사용할 때 설정 610 | 611 | - `http.cors.allow-origin: "*"` 612 | 613 | - 웹 브라우저로 접근할 수 있는 IP ACL 설정 614 | - 특정 사용자들만 사용할 수 있게 설정 615 | - ex) `"10.10.10.*", "*"` 616 | 617 | - 참고: cors (Cross-Origin Resource Sharing) 618 | 619 | - 만약 다른 사이트로 부터 데이터를 요청하길 원한다면, CORS를 enable해야 한다. 620 | 621 |

622 | 623 | #### 참고: what if... 멀티 path.data 중, 하나를 제거했을 때 (awareness로 해결??) 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | - path별 샤드 위치 632 | 633 | | data1 | data2 | 634 | |:-----:|:-----:| 635 | | 0 2 | 1 | 636 | | 4 | 1 3 | 637 | | 0 3 4 | 2 | 638 | 639 | - 인덱스의 uuid, 이 디스크에 몇번 샤드가 들어있는지 확인할 수 있음 클러스터 멀티패스를 쓰더라도, 640 | 641 | - 하나의 노드에는 primary와 replica가 같이 존재 안함 642 | 643 | - 내린다음에 어떤 샤드에 이상 생길지 확인하고, 빼고, 다시 올리면 됨, 다른노드에 있는 똑같은 샤드가 다시 복제됨 644 | 645 |

646 | 647 | ### 2. static settings: jvm.options 648 | 649 | - `Xms16g` 650 | - 최소 힙사이즈 크기 설정 651 | - `Xms16g` 652 | 653 | - 최대 힙사이즈 크기 설정 654 | 655 | ##### initial size와 maximum size를 동일하게 설정 권고 656 | 657 | - runtime에서 힙 사이즈 조정 비용이 크다. 658 | 659 | - heap size 조정 중 JVM이 잠시 멈출 수 있다. 660 | 661 | ##### 크면 클수록 많은 데이터를 heap에서 사용 가능 662 | 663 | - GC 발생 시 성능 저하 고려 664 | 665 | ##### 가능하면 물리 메모리의 50%를 넘지 않도록 권고 666 | 667 | - 최초 인덱싱이 일어날 때 시스템 버퍼 캐시를 통해 segment로 적재 668 | 669 | - 검색이나 어그리게이션이 일어날 때에도 heap영역에 데이터가 없으면??? 670 | 671 | - 먼저, 버퍼 캐시에 있는 segment를 확인 672 | 673 | - 디스크 I/O를 피하기 위한 충분한 버퍼 캐시를 확보하도록 권고 674 | 675 | ##### 32G를 넘지 않도록 권고 676 | 677 | - heap에 데이터를 OOP(Ordinary Object Point)구조체로 저장 678 | 679 | - 아키텍처 별로 32bit와 64bit크기의 주소 참조 680 | 681 | - 64bit는 메모리 참조의 영역이 넓어 성능 저하 682 | 683 | - 최대한 32bit를 이용하기 위해 메모리 주소의 offset을 가르키는 compressed OOP를 활용 684 | 685 | - 최대 32G까지 참조 가능 686 | 687 | - heap을 더 할당할 경우 자동적으로 64bit OOP를 사용 688 | 689 |
690 | 691 | ### 3. static settings: log4j2.properties 692 | 693 | - elasticsearch는 log4j2를 사용하여 어플리케이션 로그를 기록 694 | 695 | ##### - \$\{sys:es.logs.base_path} 696 | 697 | - Log 설정 디렉토리 698 | - `path.logs` 699 | 700 | ##### - \$\{sys:es.logs.cluster_name} 701 | 702 | - 클러스터 이름 703 | - `cluster.name` 704 | 705 | ##### - \$\{sys:es.logs.node_name} 706 | 707 | - 노드 이름 708 | - `node.name` 709 | 710 |
711 | 712 | ex)
\$\{sys:es.logs.base_path}\$\{sys:file.separator}\$\{sys:es.logs.cluster_name}.log
/var/log/elasticsearch/mycluster.log 713 | 714 |
715 | 716 | #### 로그의 종류 717 | 718 | - \$\{sys:es.logs.base_path}\$\{sys:file.separator}\$\{sys:es.logs.cluster_name}.log 719 | - 클러스터 운영로그 설정 720 | - \$\{sys:es.logs.base_path}\$\{sys:file.separator}\$\{sys:es.logs.cluster_name}_deprecation.log 721 | - Elasticsearch 에서 수행되고 있는 Deprecated 된 기능 정보 722 | - \$\{sys:es.logs.base_path}\$\{sys:file.separator}\$\{sys:es.logs.cluster_name}_index_search_slowlog.log 723 | - 인덱스 검색 슬로우 로그 정보 724 | - \$\{sys:es.logs.base_path}\$\{sys:file.separator}\$\{sys:es.logs.cluster_name}_index_indexing_slowlog.log 725 | - 인덱스 인덱싱 슬로우 로그 정보 726 | - \$\{sys:es.logs.base_path}\$\{sys:file.separator}\$\{sys:es.logs.cluster_name}_access.log 727 | - X-Pack auditing 로그 정보 728 | 729 |
730 | 731 | #### elasticsearch는 많은 파일에 다량의 접근 시도 732 | 733 | - 열 수 있는 file descriptor 가 부족하면 데이터 손실 가능성 발생 734 | 735 | ```shell 736 | sudo vi /etc/security/limits.conf 737 | # 추가 738 | elasticsearch soft nofile 65536 elasticsearch hard nofile 65536 739 | ``` 740 | 741 | - Elasticsearch는 operations type 에 따라 많은 thread pool 을 사용 742 | 743 | - elasticsearch 유저가 적어도 4096 개의 프로세스를 다룰 수 있어야 함 744 | 745 | ```shell 746 | elasticsearch soft noproc 4096 747 | elasticsearch hard noproc 4096 748 | ``` 749 | 750 | - elasticsearch 환경 변수가 정의되어 있는 파일`sudo vi /etc/sysconfig/elasticsearch` 751 | 752 | - elasticsearch 는 인덱스를 Filesystem 에 쓸 때 mmap 을 사용 753 | 754 | ```shell 755 | sudo vi /etc/sysctl.conf 756 | # 추가 757 | vm.max_map_count=262144 758 | #/etc/sysctl.conf 파일내용 적용 759 | sudo sysctl -p 760 | ``` 761 | 762 | - Swap Disabling 763 | 764 | - 디스크로 swap out 이 되면 성능 저하가 발생 765 | 766 | ```shell 767 | # /etc/fstab에 스왑 장치로 인식한 모든 장치를 스왑에서 해제한다. 768 | sudo swapoff -a 769 | # sysctl.conf 열기 770 | sudo vi /etc/sysctl.conf 771 | # 추가 772 | vm.swappiness = 1 773 | # 변경내용 적용 774 | sudo sysctl -p 775 | ``` 776 | 777 |
778 | 779 | ### 4. dynamic settings 780 | 781 | - 클러스터에 API로 호출 782 | - 클러스터 단위로 설정 783 | 784 |




785 | 786 | elasticsearch 클러스터 운영 787 | --------------------------- 788 | 789 | ### Rolling Restart 790 | 791 | - 무중단 운영을 위한 작업방법 792 | - 시스템 작업이나 es version upgrade 를 해야하는 상황 793 | - replica가 있는 cluster의 경우, application restart나 system reboot을 할 때마다 cluster 내부에서는 주인을 잃은 샤드들(unassigned)이 기본 라우팅 설정에 따라서, 복구를 위해 자동으로 재분배 794 | - 많은 노드들을 작업해야 할 때면, 이런 shard들이 재분배 되기를 기다렸다가 cluster가 green상태가 될 때 까지는, 시간 뿐 아니라 네트워크와 Disk I/O 등의 많은 리소스를 필요 795 | - 이런 작업을 할 때, 리밸런싱이 일어나지 않게 하는 것이 Rolling Restart 796 | - `_cluster/settings`의 `cluster.routing.allocation.enable` 값 변경에 따른 설정 변경 797 | - shard 종류에 따라 어떻게 처리 할 것인지 결정 798 | - `none` : 전부다 재분배 안하겠다. 799 | - `all` : 전부 재분배 하겠다. 800 | 801 |
802 | 803 | #### 과정 804 | 805 | 1. \_cluster API로 클러스터 라우팅 할당을 off로 변경 806 | 807 | ```json 808 | PUT _cluster/settings 809 | { 810 | "transient" : { 811 | "cluster.routing.allocation.enable" : "none" 812 | } 813 | } 814 | ``` 815 | 816 | 817 | 818 | 2. 작업하고자 하는 노드 중지 (itmare-data02 중지) 819 | 820 | - 중지된 노드의 샤드들이 unassigned 상태로 변경 (라우팅 할당을 off했으므로 리발란싱이 일어나지 않음) 821 | 822 | 823 | 824 | 3. 노드 재가동, 클러스터에 추가 확인 825 | 826 | 827 | 828 | 4. 확인 후, 라우팅 할당 on 829 | 830 | ```json 831 | PUT _cluster/settings 832 | { 833 | "transient" : { 834 | "cluster.routing.allocation.enable" : "all" 835 | } 836 | } 837 | ``` 838 | 839 | 840 | 841 | - unassigned 샤드가 추가된 노드로 복구 842 | 843 | 5. 위의 과정 노드별 반복 844 | 845 |

846 | 847 | ### Shard Allocation 848 | 849 | - 안정적인 성능 제공을 위한 샤드 분배 방법 850 | - es 운영 중 여러대로 구성된 클러스터에 노드별 용량이 상이해지는 경우가 발생한다. 851 | - 생성되는 인덱스의 샤드가 노드수와 동일하다면 큰 차이가 발생하지 않겠지만, 운영하다보면 노드 증설 등으로 인해 기존에 계획한대로 샤드 배치가 되지 않는다. 852 | - 노드에 샤드가 똑같이 분배되지 않을 때에 용량 격차가 벌어진다. 853 | 854 | 855 | 856 | - 생성되는 index의 shard 갯수가 노드 갯수와 다를 때 857 | 858 | - shard 갯수를 계획할 때, 노드 갯수를 고려해야 한다. 859 | 860 | - 방법 861 | 862 | - `POST _cluster/reroute`사용 863 | - `PUT _cluster/settings`의 disk threshold 사용 864 | - 샤드 강제 분배 865 | 866 |

867 | 868 | ### Index setting 869 | 870 | - static index: 인덱스가 생성될때 설정, 일부는 closed index에서 설정 가능 871 | - dynamic index: live index에서 update-index-settings API를 사용해 변경 가능 872 | - [참고](https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules.html) 873 | 874 | #### 1. Static index settings 875 | 876 | - `number_of_shards`: 샤드의 갯수 877 | 878 | #### 2. Dynamic index settings 879 | 880 | - 운영중 인덱스 세팅 변경 881 | - RestAPI로 변경사항 요청 882 | - `number_of_replicas`: 운영중에 리플리카 샤드 갯수를 변경 883 | - `refresh_interval`: 세그먼트에 저장된 데이터를 검색할 수 있도록 commit point를 생성하는 주기 884 | - `routing.allocation.enable`: 데이터 노드에 샤드를 어떤 방식으로 할당할 것인지를 결정 885 | - `routing.rebalance.enable`: 데이터 노드에 샤드를 어떤 방식으로 재배치할 것인지를 결정 886 | 887 | - `"index:{}"`없이 사용시, `routing.__.enable`앞에 `index.` 붙여야 한다. 888 | 889 | - 차이점? 890 | 891 | - allocation: unassigned 샤드를 노드에 배치시킨다. 892 | - rebalance: es가 클러스터에 존재하는 샤드들의 수를 카운트해 노드에서 노드로 재배치하며 발란싱을 맞춘다. 893 | 894 | - 새로운 노드가 추가될때, 오래된 샤드의 움직임을 피하기위해 더 나은 셋팅 방법은? 895 | 896 | - 준비중??? 897 | 898 | - other settings 899 | 900 | - Analysis, Mapping, Slowlog 901 | 902 | - 그중, Mapping 903 | 904 |

905 | 906 | #### Mapping 907 | 908 | - document가 indexing 될 때, doc과 doc에 포함된 field들을 어떻게 저장할지를 결정하는 과정 909 | - 6.x 부터 Multi Mapping Deprecated 910 | - Dynamic Mapping 911 | - es가 인입되는 document를 보고, 알아서 타입을 찾아 mapping 912 | - Static mapping 913 | - 사용자가 정의한 스키마를 기준으로 mapping 914 | 915 |
916 | 917 | - Mapping 할때 918 | 919 | ```shell 920 | # mapping first (create index) 921 | PUT my_index 922 | { 923 | "mappings":{ 924 | "_doc":{ 925 | "properties":{ 926 | "my_field":{ 927 | "type": "text" 928 | } 929 | } 930 | } 931 | } 932 | } 933 | 934 | # mapping update 935 | PUT my_index/_mapping/_doc 936 | { 937 | "properties":{ 938 | "my_field":{ 939 | "type": "text" 940 | } 941 | } 942 | } 943 | 944 | # mappig with dataset (create index with dataset) 945 | PUT my_index/_doc/1 946 | { 947 | "my_field": "hello world" 948 | ... 949 | } 950 | 951 | 952 | ``` 953 | 954 | ##### 1. Dynamic field Mapping 955 | 956 | | JSON Value Type | mapping Field / Description | 957 | |:---------------------:|:-----------------------------------:| 958 | | null | No field is added | 959 | | true of false | boolean field | 960 | | floating point number | float field(log) | 961 | | integer | long field | 962 | | object | object field | 963 | | array | string or object field | 964 | | data string | double or long field | 965 | | text string | text field with a keyword sub-field | 966 | 967 | ##### 2. Dynamic template 968 | 969 | - field기반으로 다이나믹하게 적용되는 custom mapping을 정의 할 수 있다. 970 | 971 | ```shell 972 | # example 973 | PUT my_index 974 | { 975 | "mappings":{ 976 | "_doc":{ 977 | "dynamic_templates":[ 978 | { 979 | "my_template_1":{ ##=> 1) 980 | "match_mapping_type": ... ##=> 2) 981 | "mapping": { ... } ##=> 3) 982 | } 983 | }, 984 | { 985 | "my_template_2":{ ##=> 1) 986 | "match": ... ##=> 2) 987 | "mapping": { ... } ##=> 3) 988 | } 989 | } 990 | ] 991 | } 992 | } 993 | } 994 | ``` 995 | 996 | - 1) template name 마음대로 정하기 997 | - 2) match condition 포함할 수 있다. (`match_mapping_type`, `match`, `match_pattern`, `unmatch`, `path_match`, `path_unmatch`\) 998 | - 3) matched field가 사용 할 mapping 999 | 1000 | | 이름 | 분류 | 설명 | 1001 | |:--------------------:|:----------------:|:-------------------------------------------------------------------:| 1002 | | `match_mapping_type` | datatype | json parser로 부터 detect된 datatype | 1003 | | `match` | name of field | field name과 매치하기 위한 패턴을 사용 | 1004 | | `unmatch` | name of field | field name과 매치되지 않는 패턴을 사용 | 1005 | | `match_pattern` | name of field | regex를 활용해서 `match`의 행위를 조절 | 1006 | | `path_match` | full dotted path | `match`와 같지만, full dotted path (eg. some_object.*.some_field) | 1007 | | `path_unmatch` | full dotted path | `unmatch`와 같지만, full dotted path (eg. some_object.*.some_field) | 1008 | | `mapping` | mapping | 기존 mapping과 동일 | 1009 | 1010 |

1011 | 1012 | #### Template 1013 | 1014 | - 미리 정의된 템플릿으로 인덱싱하기 1015 | - 익덱스가 생성될 때 사용자 정의된 세팅이나 매핑을 자동으로 적용 1016 | - 인덱스 패턴, 인덱스 세팅, 인덱스 매핑 관련 사항 정의 1017 | - 인덱스가 생성될 때 패턴이 매칭되는 인덱스는 해당 정의를 따름 1018 | - order가 높은 번호가 낮은 번호를 override하여 merging 1019 | 1020 |

1021 | 1022 | ### hot-warm data node 1023 | 1024 | - elasticsearch 5.x부터, 1025 | - master node: 클러스터 관리 상태를 핸들링하는 노드 1026 | - 데이터가 없다. 1027 | - 서치 작업에 참여하지 않는다. 1028 | - 인덱싱하지 않는다. 1029 | - 데이터노드에 비해 적은 CPU, RAM, Disk configuration 1030 | - hot node: 빈번하게 호출되거나 자주 쿼리 작업하는 인덱스 1031 | - 가장 자주 쿼리되는 가장 최신 인덱스를 홀드 1032 | - 가장 파워풀해야하는 서버 1033 | - high availability를 위해 적어도 3개의 노드 추천 1034 | - warm node: 자주 호출되지 않는, 읽기 전용의 대용량의 인덱스를 처리 1035 | - 자주 쿼리되지 않는 대용량 read-only 인덱스를 헨들링 1036 | - high availability를 위해 적어도 3개의 노드 추천 1037 | - elk할때 사용, 검색엔진으로는 잘 안씀 1038 | - es에선 빠른 응답을 위해 SSD 디스크를 사용하는 것을 권고 1039 | - index가 크고 보관기간이 길명 비용 부담이 증가 1040 | - 최근 데이터를 더 자주 보는 경향을 이용한 매커니즘 1041 | - 상대적으로 비용이 저렴, 고용량인 SATA 디스크를 이용 1042 | - elasticsearch.yml, Template, Curator 를 이용하여 운영! 1043 | 1044 |




1045 | 1046 | elasticsearch API 활용 1047 | ---------------------- 1048 | 1049 | - es는 여러가지 API를 두어 온라인 상의 사용이나 운영의 편이를 도모 1050 | - 운영을 위해 클러스터 상태나 지표들을 볼 수 있는 모니터링 API 1051 | - 클러스터의 설정을 변경할 수 있는 클러스터 설정변경 API 1052 | - 데이터를 이관하거나 별칭을 달 수 있는 API 등 1053 | 1054 |
1055 | 1056 | ### Cluster API - 클러스터 운영 API 다루기 1057 | 1058 | - POST \_cluster/... 1059 | - 운영중인 클러스터의 세팅정보 확인이나 온라인 상태로 설정을 변경할 수 있는 API 1060 | - 자주 변경할 여지가 있는 사항들은 cluster api로 진행 1061 | - 설정 모드는 두 가지로 나뉨 1062 | - Transient: full cluster restart 시, 리셋되는 설정 1063 | - Persistent: 사용자 변경없으면, 영구 보존되는 설정, static setting보다 우선순위가 높음 1064 | 1065 |
1066 | 1067 | ### Reindex API - 데이터 마이그레이션 1068 | 1069 | - POST \_reindex 1070 | - 인덱스를 복제할 때 사용 1071 | - 원본 인덱스의 세팅이나 매핑은 복제되지 않는다. 1072 | - 클러스터 내부 뿐 아니라 외부 클러스터의 인덱스도 복제 가능 1073 | 1074 |
1075 | 1076 | ### Bulk API - 도큐먼트 한번에 인덱싱하기 1077 | 1078 | - 인덱스문서의 인덱싱, 삭제, 업데이트를 벌크로 진행할 수 있는 API 1079 | - 사용가능한 action은 `index`, `create`, `delete`, `update` 1080 | - `index` action: 다음 라인에는 source가 와야한다. 해당 doc id가 존재하면, doc 업데이트 1081 | - `create` action: 다음 라인에는 source가 와야한다. 해당 doc id가 존재하면, 실행 실패 1082 | - `update` action: 변경할 source를 다음 라인에 `"doc"`과 함께 추가, 해당 doc id가 없으면 ( `"result" : "not_found"` ) 1083 | - `delete` action: source추가 필요없음 1084 | - Java, Python, Perl 등 언어별로 bulk api 라이브러리 제공 [링크: bulk API](https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html) 1085 | 1086 |
1087 | 1088 | ### 그 외 운영에 유용한 API 1089 | 1090 | - \_aliases API 1091 | - 인덱스에 별칭 부여하는 API 1092 | - \_reindex API와 함께 자주 사용 1093 | - 존재하는 인덱스와 같은 이름으로는 설정 불가 1094 | - \_forcemerge API 1095 | - segment를 강제로 병합하는 API 1096 | - 인덱싱 중인 인덱스에 사용은 비추!!! 1097 | - 인덱싱이 끝난 인덱스는 하나의 segment로 merge를 추천!!! 1098 | - I/O 비용이 크기 때문에 인덱싱이나 검색이 없는 시간대에 진행 1099 | - \_open/close API 1100 | - 인덱스의 상태를 open/close 할 수 있는 API 1101 | - close된 인덱스는 read/write 불가 1102 | - 클러스터 전체 샤드에서 제외 1103 | - 라우팅 disabled 1104 | 1105 | 1106 | 1107 |









1108 | 1109 | --- 1110 | 1111 | Elasticsearch 검색엔진 활용 및 성능 최적화와 모니터링 1112 | ===================================================== 1113 | 1114 | --- 1115 | 1116 |
1117 | 1118 | 검색엔진으로 Elasticsearch 활용하기 1119 | ----------------------------------- 1120 | 1121 |
1122 | 1123 | ### 인덱스 생성 과정 1124 | 1125 | - 인덱싱 필수 조건 1126 | 1127 | - 프라이머리 샤드가 항상 먼저 writing 되야 한다. 1128 | - primary shard의 writing이 전부 완료 되면, replica shard 복제가 된다. 1129 | 1130 | - Inverted Index 1131 | 1132 | - 인덱싱되어 들어온 문서는 inverted index형태로 segment에 저장 1133 | - 정의된 Analyzer에 의해 tokenizing된 단어를 기준으로 indexing 1134 | - 별도로 정의하지 않으면 기본 standard analyzer가 적용(언어 문법 기준 파싱) ![inverted_index](./pictures/inverted_index.png) 1135 | - 1. 문서가 들어오면 analyzer가 용어별로 나열 1136 | - 2. 용어가 몇번 들어왔는데 갯수 정리 1137 | - 3. 용어가 몇번 문서에 있는지 metadata형태로 저장 1138 | - 4. 세그먼트 저장되기 전에 버퍼에 저장되어있다가 리프래쉬되면 세그먼트에 쓰여진다. 1139 | - 한줄요약: analyzer가 문서가 들어오면 문서를 쪼개서 inverted index형태로 만든 후에 세그먼트로 저장 1140 | 1141 | ### 분석기 변경 방법 1142 | 1143 | - Analysis 1144 | 1145 | - text에 대해 검색이 될 수 있도록 분석하는 과정 1146 | 1147 | ![analysis-chain](./pictures/analysis-chain.png) 1148 | 1149 | - character filters 1150 | 1151 | - **0~3개 사용가능**, 대괄호(`[ ]`) 안에 들어감 1152 | - 원본 text 가공 1153 | - 설정하지 않거나 다중으로 필터 설정 가능 1154 | - ex) html 태그 제거, 패턴 매칭(123-456-789 ==> 123_456_789) 1155 | - `html_strip`, `mapping`, `pattern_replace` 1156 | - [custom analyzers](https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-custom-analyzer.html) 1157 | 1158 | - Tokenizer 1159 | 1160 | - **1개만 사용** 1161 | - 어떤 방식으로 원본 text를 tokenizing 할지 결정 1162 | - tokenizing 된 term은 token 이라 부름 1163 | - 하나의 tokenizer만 설정 가능 1164 | - ex) space가 기준일때: You are a boy!!! ==> You / are / a / boy!!! 1165 | - `standard`, `letter`, `lowercase`, `whitespace` 등등 1166 | 1167 | - Token filters 1168 | 1169 | - **0~n개 사용가능**, 대괄호(`[ ]`) 안에 들어감 1170 | - tokenizer에 의해 결정된 token들에 대한 가공 1171 | - 설정하지 않거나 다중으로 필터 설정 가능 1172 | - 다중 필터 사용시, 순서 중요, 만약 `stop` 필터를 `lowercase`보다 앞에 위치하면, the로 시작하는 문장의 "The"를 고유명사로 인식하여 필터링 되지 않는다. 1173 | - ex) stopword제거: You / are / a / boy ==> you / boy 1174 | - lowercasing, stopwords, synonyms 1175 | 1176 | - Analyzer 1177 | 1178 | - default는 standard analyzer, 변경가능, 사용자 정의 analyzer 설정 가능 1179 | - analyzer API를 통해 분석되는 token 확인 가능 1180 | 1181 | - Analyer 가 바뀌면 token도 변경 1182 | 1183 | - 검색할 단어가 바뀌므로 중간에 Analyzer를 변경하면 의도와 다른 결과 가져오게 됨 1184 | 1185 | - **Analyzer를 변경하면 반드시 \_reindex 필요** 1186 | 1187 | - template 1188 | 1189 | ```shell 1190 | analysis 1191 | 1192 | ``` 1193 | 1194 | - 참고 링크 1195 | 1196 | - [Character filters](https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-charfilters.html) 1197 | - [Tokenizer](https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-tokenizers.html) 1198 | - [Token filters](https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-tokenfilters.html) 1199 | 1200 |



1201 | 1202 | ### 쿼리 생성 1203 | 1204 | #### 검색하기 1205 | 1206 | - \_search API를 활용해 원하는 document 검색 1207 | - URI 및 HTTP request body를 통해 쿼리 작성 1208 | - 구성 1209 | - Query: 문서의 위치를 찾는다. 1210 | - Fetch: 문서를 가져온다. 1211 | 1212 | ```shell 1213 | # example 1214 | GET /_search 1215 | { 1216 | "from": 90, 1217 | "size": 10 1218 | } 1219 | ``` 1220 | 1221 |
1222 | 1223 | #### Query Phase of distributed search 1224 | 1225 | - 쿼리를 받아, 문서가 어떤 node의 어떤 shard에 있는지 찾는 과정 1226 | - from, size를 계산하여 빈 queue를 생성 1227 | - 전체 node, shard에 문서가 있는지를 확인, node들도 로컬에 queue를 생성 1228 | - queue에 검색된 문서의 id를 넣고 결과를 sorting 후 결과 리턴 1229 | 1230 | ![search_query](./pictures/search_query.png) 1231 | 1232 | 1. client는 `search` 요청을 `from + size`크기의 empty priority queue를 만드는 `node 3`에게 보낸다. 1233 | 2. `node 3`는 search 요청을 index에 있는 모든 shard의 primary와 replica 포워딩한다. 각각의 shard는 query를 local에서 실행하고, 결과를 local sorted priority queue(size = `from + size`)에 추가 시킨다. 1234 | 3. 각 shard는 doc ID를 리턴하고, priority queue의 모든 doc 값을 coordinating node, `node 3`에 정렬한다. coordinating node는 그 값들을 결과값이 global하게 정렬된 리스트를 생산하기위해 자신이 소유한 priority queue안에 합친다. 1235 | 1236 | #### Fetch phase of distributed search 1237 | 1238 | - 리턴 받은 document ID를 기준으로 관련된 shard에 multi GET 요청 1239 | - 노드별로 리턴받은 문서를 클라이언트에게 리턴 1240 | 1241 | ![search_fetch](./pictures/search_fetch.png) 1242 | 1243 | 1. coordinating node(`node 3`)은 어떤 document가 fetch되는지를 확인하고, multi GET 요청을 적절한 shard에 발행한다. 1244 | 2. 각 shard는 document를 로드하고, 그 document들을 *enriches* 한다. 그러고나섯 필요시, document들을 coordinating node에 리턴한다. 1245 | 3. 모든 document가 fetch되고, coordinating node는 결과를 client에게 리턴한다. 1246 | 1247 | #### URL search 1248 | 1249 | - URL에 request parameters를 통해 검색 질의 1250 | - 한정된 검색 옵션만 사용 가능 (Quick Test) 1251 | - ex) `GET bank/_search?from=0&size=100&q=address:Fleet&sort=age:asc` 1252 | - [URL search에 대한 더 많은 정보](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-uri-request.html) 1253 | 1254 | #### Request Body Search 1255 | 1256 | - Query DSL(Domain Specific Language)를 이용해 HTTP Body 정의 후, 질의 1257 | - query 구문을 사용하여 질의 1258 | - from과 size parameter를 이용하여 pagination한다. (크기를 정한다.) 1259 | - default는 from:0, size:10 1260 | - (from + size)가 기본으로는 10000까지만 허용 1261 | - 더 필요하면 index.max_result_window 조정 필요 1262 | - [Request Body Search에 대한 더 많은 정보](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-body.html) 1263 | 1264 |



1265 | 1266 | ### Query DSL (Domain Specific Language) 1267 | 1268 | - JSON 기반의 es쿼리를 정의하는 언어 1269 | 1270 | #### Leaf query clause 1271 | 1272 | - 자체적으로 쿼리를 할 수 있는 완성된 검색 쿼리 절 1273 | - match, term, range 등 1274 | 1275 | ##### 1. Full Text Query (Query Context) 1276 | 1277 | - query를 analyze하여 검색, 스코어가 가장 높은 문서순으로 노출 1278 | - 검색 쿼리 절이 얼마나 문서에 잘 매치되는지 유사성을 확인 1279 | - 검색 쿼리와의 매칭율에 따라 `_score`를 부여 1280 | - ex) elasticsearch 검색 => elastic에 포함된 문서, search에 포함된 문서 검색 1281 | - match, match_phrase, match_phrase_prefix, query_string 등 사용 1282 | 1283 | ##### 2. Term Level Query (filter Context) 1284 | 1285 | - 정확히 일치하는 용어만 검색, `_score`는 무의미 1286 | - keyword field 기반으로 검색 1287 | - ex) date 필드의 값이 2015년과 2018년 사이에 속해있는지, status 필드의 값이 'ok'인지 1288 | - term, terms, range 등 사용 1289 | 1290 | #### Compound query clause 1291 | 1292 | - Leaf query 및 compound query를 결합하여 multiple query를 만들거나, 쿼리의 행동을 변경한다 1293 | 1294 | - combine multi query: bool, boosting, dis_max 등 1295 | - alter query: constant_score 등 1296 | 1297 | - bool Query 1298 | 1299 | - 하나 이상의 boolean clause가 사용됨 1300 | 1. must: 문서에 일치하는 항목, 스코어 계산 1301 | 2. filter: 문서에 일치하는 항목, 스코어 0, filter context에서 보통 실행 1302 | 3. should: 문서에 일치하는 항목, must나 filter항목이 없으면 적어도 하나의 쿼리절과 일치되는 결과 리턴 1303 | 4. must_not: 문서에 일치하지 않는 항목 1304 | - 다른 설명 1305 | 1. must : 반드시 매칭되는 조건, score에 영향을 준다. 1306 | 2. filter : must와 동일한 동작하지만, score에 영향을 주지 않는다. 1307 | 3. should : bool 쿼리가 query context에 있고 must 또는 filter 절이 있다면, should 쿼리와 일치하는 결과가 없더라도 매치가 된다. bool 쿼리가 filter context 안에 있거나, must 또는 filter 중에 하나라도 있는 경우에만 매칭된다. minimum_should_match 이 값을 지정해서 컨트롤할 수 있다. 1308 | 4. must_not : 이 쿼리와 매칭되지 않아야 한다. 1309 | 1310 | - [링크: Query DSL](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html) 1311 | 1312 |



1313 | 1314 | Elasticsearch 색인 성능 최적화 1315 | ------------------------------ 1316 | 1317 | - 색인은 I/O job 1318 | - es에서 기본으로 제공하는 색인 기능 중 불필요 기능 제거 1319 | - 인덱스 mapping스키마를 미리 적절히 정의하는 것만으로도 성능 향상 1320 | - 니즈에 따라 데이터 제공 패턴을 변경하여 성능 향상 1321 | 1322 |

1323 | 1324 | ### 미리 정해놓은 스키마로 리소스를 절약할 수 있는 static mapping 적용하기 1325 | 1326 | - Mapping 1327 | - 문서가 인덱싱 될때 문서와 문서에 포함된 필드들을 어떻게 저장할지를 결정하는 과정 1328 | - string에 대해 text field로 쓸지, keyword field로 쓸지 1329 | - numeric type은 short field로 쓸지, log field로 쓸지 1330 | - date type은 어떻게 정의해서 쓸지 1331 | - Field Datatype 1332 | - field type: text, keyword, date, long, double, boolean ... 1333 | - [참고](https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html) 1334 | 1335 | #### 1. text field type 1336 | 1337 | - email본문 같은 full-text로 인덱싱 되는 필드타입 1338 | - 분석기를 통해 단어로 검색 가능하도록 인덱싱됨 1339 | - sorting에 사용되지 않음 1340 | - aggregation에 거의 사용되지 않음 1341 | 1342 | ```shell 1343 | PUT text_index 1344 | { 1345 | "mappings":{ 1346 | "_doc":{ 1347 | "properties":{ 1348 | "title":{ 1349 | "type": "text" 1350 | } 1351 | } 1352 | } 1353 | } 1354 | } 1355 | ``` 1356 | 1357 |
1358 | 1359 | #### 2. keyword field type 1360 | 1361 | - email 주소나 호스트 네임같은 구조화된 컨텐츠로 인덱싱되는 필드 타입 1362 | - Analyze 되지 않음 1363 | - sorting, aggregation 지원 1364 | - Exact value로만 검색된다. 1365 | 1366 | ```shell 1367 | PUT keyword_index 1368 | { 1369 | "mappings": { 1370 | "_doc":{ 1371 | "properties:"{ 1372 | "title":{ 1373 | "type": "keyword" 1374 | } 1375 | } 1376 | } 1377 | } 1378 | } 1379 | ``` 1380 | 1381 |
1382 | 1383 | - Aggregation? 1384 | - 검색 쿼리에 의해 집계/통계를 내는 프레임 워크 1385 | - 메일 본문같은 긴 내용은 집계/통계를 내기 어려운 데이터 1386 | - 수치나 특정 문자로 한정된 데이터들의 집계를 내는 역할 1387 | - kibana에서 집계/통계를 낼 때 주로 사용 1388 | - SQL GROUP BY나 SQL 집계 기능과 대략 같다고 생각 1389 | 1390 |

1391 | 1392 | ##### text vs. keyword 1393 | 1394 | - dyanmic mapping으로 string이 들어오면 text와 keyword 둘 다 사용 가능 1395 | - fields로 sub field 세팅 1396 | - sub field는 test.keyword로 질의 1397 | - 인덱싱 될 때 text는 analyzer를 거치게 된다. 1398 | - keyword로 사용할 의도였다면 이러한 분석은 낭비 1399 | - keyword로 사용할 string이라면 keyword type으로 매핑 1400 | 1401 | | 항목 | text | keyword | 1402 | |:----------------:|:------:|:-------:| 1403 | | input | String | String | 1404 | | analyze | O | X | 1405 | | Full-text Search | O | X | 1406 | | Sorting | X | O | 1407 | | Aggregation | X | O | 1408 | 1409 |
1410 | 1411 | #### 3. date field type 1412 | 1413 | - 형식이 지정된 날짜가 포함 된 문자열 (ex: "2019/01/01 01:14:15") 1414 | - milliseconds를 나타내는 epoch_millis (ex: 1546305255000) 1415 | - 허용할 타입만 지정 또한 가능하다. 1416 | 1417 | ```shell 1418 | PUT date_index 1419 | { 1420 | "mapping": { 1421 | "_doc":{ 1422 | "properties":{ 1423 | "date":{ 1424 | "type": "date" 1425 | } 1426 | } 1427 | } 1428 | } 1429 | } 1430 | ``` 1431 | 1432 |
1433 | 1434 | #### 4. Numeric field type 1435 | 1436 | - 숫자 형식의 필드 타입 1437 | - 적절하게 맞추면 좋으나 동일 타입으로 통일을 권고 1438 | - dynamic 매핑은 long 1439 | 1440 | | Value Type | Supported | 1441 | |:------------:|:----------------------------------------------:| 1442 | | long | 64-bit integer (-2^63 ~ 2^63-1) | 1443 | | integer | 32-bit integer (-2^31 ~ 2^31-1) | 1444 | | short | 16-bit integer (-32,768 ~ 32,767) | 1445 | | byte | 8-bit integer (-128 ~ 127) | 1446 | | double/float | 64-bit \ 32-bit IEEE 754 floating point number | 1447 | 1448 |
1449 | 1450 | ### hierachiacl nature of JSON field type 1451 | 1452 | - object 나 list같이 게층구조의 데이터는 properties 라 불리는 서브 필드에 포함된다. 1453 | - properties는 서브필드로 활용 1454 | - 매핑을 정의해서 인덱스를 만들때 1455 | - 매핑타입을 추가할 때 1456 | - 매핑을 정의하지 않고 문서를 인덱싱 할 때 Elasticsearch가 dynamic하게 매핑을 정의할 때 1457 | 1458 | #### 5. object field type 1459 | 1460 | - `object` for single JSON objects 1461 | 1462 | #### 6. nested field type 1463 | 1464 | - `nested` for arrays of JSON objects 1465 | - `nested`로 정의한 매핑은 인덱싱이 되는 순간 다시 dynamic mapping으로 인덱싱 1466 | - static mapping으로 별도 지정 1467 | 1468 |


1469 | 1470 | ### 필요하지 않다면 쓰지 말아야 할 기능들, \_all 필드 1471 | 1472 | - 도큐먼트의 모든 필드의 value를 합쳐서 인덱싱하는 필드 1473 | - 검색할 때 사용되며, 세그먼트에 저장되지는 않지만 힙 영역에 올라가는 데이터 1474 | - text field로 analyze 되는 필드 (text field로 저장됨) 1475 | - 6.0부터 deprecated (가급적 안쓰는게 좋음) 1476 | - \_all field를 5버전 이하에서 사용한다면 disable 권고 1477 | - 탬플릿에 `_default_`type을 통해 전체 인덱스 disable 1478 | - key/value 형태로 저장해서 검색하는 걸 권고 1479 | 1480 | ```json 1481 | PUT twitter 1482 | { 1483 | "mappings":{ 1484 | "_default_":{ 1485 | "_all":{ 1486 | "enabled":false 1487 | } 1488 | } 1489 | } 1490 | } 1491 | ``` 1492 | 1493 |

1494 | 1495 | ### 인덱싱 된 데이터를 검색 결과에 반영할 수 있도록 refresh_interval 변경하기 1496 | 1497 | - 메모리 캐시 버퍼 영역으로부터 세그먼트에 도큐먼트를 저장하는 주기 1498 | - refresh가 되어, 저장된 도큐먼트는 검색 가능한 상태로 변경된다. 1499 | - 온라인상에서 인덱스별 세팅 가능 1500 | - -1로 설정하면 disable, null로 설정하면 1s로 초기화 1501 | - 주로 bulk indexing할 때 -1로 설정하고 사용 1502 | - interval을 길게 가져갈수록 I/O 빈도가 낮아져 성능 향상 1503 | - 메모리 버퍼의 용량을 고려하여 interval을 설정 1504 | 1505 |
1506 | 1507 | ##### \*\*\* -1로 설정했음에도 refresh thread가 증가 하는 상황 \*\*\* 1508 | 1509 | - 기본적으로 -1 설정은 bulk indexing 할때, refresh action을 수행하지 못하게 하기 위해 1510 | - refresh thread 확인 (증가 시, mapping정보에서 dynamic field에 따른 template 구성이 영향을 줄 수 있음) 1511 | - dynamic field설정으로 indexing 할때, mapping정보가 바뀌게 되고 이를 반영 하기위해 IndexService가 updateMetaData()를 수행한다. 이 과정에서 자동으로 refresh가 발생하므로, bulk request 시, 어떤 구성을 하였는지 먼저 분석해야 한다. 1512 | 1513 |

1514 | 1515 | ### 그밖의 색인 성능 최적화 1516 | 1517 | #### Document id 없이 POST로 인덱싱 권고 1518 | 1519 | - PUT을 통해 doc id를 설정한 채로 인덱싱을 할때 es는 해당 id의 문서가 있는지 먼저 체크 1520 | - 문서가 많아질수록, 인덱스가 커질수록 해당 부하가 커짐 1521 | 1522 | #### Bulk Indexing 활용 권고 1523 | 1524 | - 가능하면 단일 인덱싱 요청보다는 한번에 많은 문서를 Bulk indexling하는것이 더 효율적 1525 | - 단일 노드, 단일 샤드 환경에서 적절한 bulk size 측정 후 진행 권고 1526 | - request reject나 gc상황을 봐가며 적정 수치 확인 1527 | 1528 |



1529 | 1530 | Elasticsearch 검색 성능 최적화 1531 | ------------------------------ 1532 | 1533 | ### 쿼리 튜닝 하기: 검색에 유리한 튜닝방법 1534 | 1535 | - numeric field에 대해 keyword field로 인덱싱 고려 1536 | - 검색과 range필드 쿼리는 가능 1537 | - 집계 등의 수치 계산 불가능 1538 | - wildcard 사용에 대해 충분히 검토 필요 1539 | - token으로 분리되는 용어는 wildcard 대신 match를 써도 충분 1540 | - exact match 검색을 할때에는 match 대신 term쿼리 사용 1541 | - 불필요한 analyze를 제외하여 성능 향 1542 | - query context와 filter context를 적절히 활용 1543 | - filter context쿼리는 스코어가 의미가 없는 쿼리 1544 | - filter절에 넣어 스코어를 계산하는 단계를 없애면 성능 향상 1545 | - bool 쿼리는 쿼리가 정이된 순서대로 실행 1546 | - 최상단에 정의된 쿼리에 결과 범위를 가장 좁힐 수 있는 쿼리를 두는게 좋다. 1547 | 1548 |
1549 | 1550 | - 서비스 전, 쿼리 캐시 warm-up 1551 | 1552 | - 처음 로딩되는 데이터는 heap에 올라와있지 않다면 버퍼 캐시에 데이터가 있는지 확인 1553 | - 버퍼캐시에도 없다면 디스크에 저장된 segment를 찾아 heap에 데이터를 올리고 리턴 1554 | - 자주 사용되는 쿼리가 짐작된다면 서비스 전에 미리 쿼리를 날려두어 heap에 데이터를 로딩 1555 | - 전체 데이터가 로딩될 만큼 힙 사이즈가 크다면 와일드카드 쿼리로 전체 데이터를 로딩 1556 | 1557 |

1558 | 1559 | ### 샤드 배치 결정하기: 검색성능을 위해 샤드를 배치하는 노하우 1560 | 1561 | - **한번 설정한 샤드 갯수는 변경 불가** 1562 | - 처음부터 샤드 갯수를 잘 설정해야 클러스터 성능이 좋아짐 1563 | - 샤드 갯수 결정 시, 고려해야 할 점 1564 | 1. **인덱스가 생성될 때, 전체 노드가 인덱싱과 검색에 참여할 수 있는가?** 1565 | - 분산처리를 위해 샤드가 노드에 고루 분배되어야 함 1566 | - 노드 갯수의 배수로 샤드 갯수를 가져가면 노드 별 용량도 비숫하게 수렴됨 1567 | 2. **하나의 데이터 노드에 적당한 샤드 갯수가 저장되도록 설계되었는가?** 1568 | - Heap size 1GB의 Heap 당, 20~25개 정도의 샤드 설정 1569 | - 데이터노드에 heap size를 16G정도로 설정, 노드 당 320~400 정도의 샤드 설정 1570 | - es커뮤니티에서 권고하는 일반 설정 1571 | - 노드 당 300개의 샤드를 넘지 않도록 권고(굉장히 쾌적히 쓸수 있는 일반적인 사항) 1572 | - use case 별로 상이할 수 있음 1573 | 3. **하나의 샤드가 적절한 용량만 저장되도록 설계되었는가?** 1574 | - 하나의 샤드 적정 크기는 보통 20~40GB를 권고 (50GB는 절대 넘기지 말도록 권고한다) 1575 | - 작을수록 좋지만 너무 작게 나누면 적체 샤드갯수가 증가 (2번 조건과 상충) 1576 | - 인덱스 전체 크기가 산정되면 하나의 샤드 크기가 적절하게 나눠질 수 있도록 설정 1577 | - ex) 매일 저장되는 인덱스의 총 크기가 500G ==> 샤드 1개가 20G만 가져갈 수 있도록 25개의 샤드 세팅 1578 | 4. **클러스터의 전체 샤드 갯수는 적절한가?** 1579 | - 클러스터 전체 샤드 갯수가 늘면 그만큼 클러스터 내 노드가 알고 있어야 하는 정보들도 많아짐 1580 | - 실제 운영 환경에서 20,000개가 넘어가는 순간부터 성능이 급격히 감소 1581 | 5. **꼭 실시간으로 replica shard가 필요한가?** 1582 | - replica shard는 실제 문서만큼의 추가 복제 비용이 발생 1583 | - 원본이 별도로 있다면 인덱싱 될 때는 replica를 없애면 성능 향상 1584 | - 데이터 유실의 위험이 있으니 상황을 잘 고려하여 판단 1585 | 1586 |
1587 | 1588 | #### 클러스터 sizing 시나리오 1589 | 1590 | - 조건 1591 | 1592 | 1. daily로 400G 정도로 인덱싱되는 문서가 들어올 예정 1593 | 2. 데이터 보존을 위해 replica 필요 1594 | 3. 10일 정도 데이터 보존 희망 1595 | 1596 | - sizing 진행사항 1597 | 1598 | 1. 먼저, 총 클러스터 인덱스 용량을 산정 1599 | 2. 400GB x 2(primary/replica) x 10 days = 8TB 1600 | 3. 하나의 샤드에 20G 적재로 산정, 20개의 primary 샤드 산정 1601 | 4. 클러스터 전체 샤드 갯수는 20 x 2(p/r) x 10 = 400 1602 | 5. 디스크가 SSD 2T라고 가정하면 8TB를 저장하고 20%정도 여유 용량 확보를 위해 5대 구매 (ssd용량이 차있으면 차있을수록 성능 감소) 1603 | 6. 인덱스 샤드가 replica 포함 총 40개이므로, 노드 당 샤드 8개 할당됨 1604 | 7. 하루 400GB의 인덱스를 모두 힙과 버퍼에 담으려면 총 800G의 메모리 필요 1605 | 8. 5대로 나누면 160G의 메모리 필요 (이렇게 커지면 하루 데이터 모두를 메모리에 담는 것은 포기) 1606 | 9. OOP 구조체를 고려하여 64GB 메모리로 구매, heap을 30G로 설정 1607 | 10. 노드 당 heap 30GB에 10일 전체 샤드는 80GB (1GB 당 3개 미만) 1608 | 1609 |
1610 | 1611 | #### \_forcemerge API 1612 | 1613 | - segment를 강제로 병합하는 API 1614 | - 인덱싱 중인, 인덱스에는 사용 **비추** 1615 | - 인덱싱이 끝난 인덱스는 하나의 segment로 merge를 추천 1616 | - I/O비용이 크기 때문에 인덱싱이나 검색이 없는 시간대에 진행 1617 | 1618 |
1619 | 1620 | #### Routing 1621 | 1622 | - routing key를 통해 특정 샤드로 인덱싱하는 방법 1623 | - routing key를, 인덱싱 샤드 할당 알고리즘을 통해 할당 1624 | - shard = hash(routing) % number_of_primary_shards 1625 | - routing key에 의해 특정 샤드로 들어간 데이터는 검색 시에 검색이 아닌 문서 가져오기 과정을 거쳐 성능이 향상됨 1626 | - ex) 1627 | 1. 메일 서비스 검색엔진을 es로 사용하고, 사용자별로 메일을 검색 1628 | 2. 사용자 id를 routing key로 주고 메일 본문을 인덱싱 1629 | 3. 검색시에 사용자 id를 routing key로 찾으면 특정 샤드만 검색 1630 | 1631 |
1632 | 1633 | #### Rollover API 1634 | 1635 | - 라우팅으로 커진 샤드를 캐어하는 방법 1636 | - 특정 조건이 맞으면 새로운 인덱스를 생성하고 alias를 옮겨주는 기능 1637 | - 특정 이름을 지정하여 생성도 가능 1638 | - ?dry_run 을 실행하면 모의실행 가능 1639 | 1640 |


1641 | 1642 | Elasticsearch 모니터링 1643 | ---------------------- 1644 | 1645 | ### rejected, 데이터의 누락이 발생하는 순간 1646 | 1647 | - 데이터의 누락이 발생하는 순간 1648 | - 노드 내에서 스레드의 메모리 사용을 관리하기 위해 여러개의 스레드풀 사용 1649 | - index, get, search, write(bulk)등 여러개의 스레드풀 존재 1650 | - 각각의 스레드풀은 대기열 큐를 두어 대기중인 요청을 보관 1651 | - `GET _node/thread_pool` 1652 | 1653 | | 종류 | 용도 | Thread Pool Type | Thread Pool Size | Queue Size | 1654 | |:-------:|:-----------------------------:|:-----------------------:|:----------------------:|:----------:| 1655 | | index | index/delete 동작 | `fixed` | core수 | 200 | 1656 | | search | count/search 동작 | `fixed_auto_queue_size` | int(core수 * 3 / 2 )+1 | 1000 | 1657 | | get | get 동작 | `fixed_auto_queue_size` | core수 | 1000 | 1658 | | write | index/delete/update/bulk 요청 | `fixed` | core수 | 200 | 1659 | | analyze | analyze 요청 | `fixed` | 1 | 16 | 1660 | 1661 | - `fixed`: 1662 | - `fixed_auto_queue_size`: 1663 | - [참고링크](https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-threadpool.html) 1664 | 1665 | - 대기열큐가 꽉차면 그 이후부터는 요청이 reject됨 1666 | 1667 | - `_nodes/stats`를 통해 모니터링 1668 | 1669 | - `_cat/thread_pool?v`을 통해 thread_pool 정보만 조회 가능 1670 | 1671 | - elasticsearch.yml 파일에 큐 사이즈 조절 관련 property 추가 가능 1672 | 1673 | ```shell 1674 | thread_pool.bulk.queue_size: 10000 1675 | thread_pool.search.queue_size: 10000 1676 | ``` 1677 | 1678 |
1679 | 1680 | ### \_cat API로 클러스터 상태 모니터링 하기 1681 | 1682 | - 클러스터의 여러가지 상태 살펴보기 1683 | - `_cat/health?v`: 자주사용, 때로는 for문돌려서 1초마다 확인하는 상황 필요 1684 | - `_cat/master?v`: 유용, 데이터 막 들어올때, 마스터노드 들어가서 확인 1685 | 1686 |
1687 | 1688 | ### \_stats, \_nodes API로 클러스터의 리소스 사용 지표 모니터링 하기 1689 | 1690 | - 클러스터의 리소스 사용 지표 확인하기 1691 | 1692 | #### Stats API 1693 | 1694 | - `GET _stat` 1695 | - Get Method를 통해 전체 클러스터, 인덱스 별 프라이머리 샤드와 전체 샤드의 각종 지표를 확인하는 API로 클러스터 모니터링 지표로 활 1696 | - docs.count: 저장된 도큐멘트 갯수 1697 | - docs.deleted: 삭제된 도큐멘트 갯수 1698 | - store: 저장된 용량(bytes) 1699 | - indexing.index_total: 인덱싱된 횟수 1700 | - indexing.index_time_in_millis: 인덱싱 할 때 소요된 milliseconds 1701 | - get.total: get 한 횟수 1702 | - get.time_in_millis: get 할 때 소요된 milliseconds 1703 | 1704 |
1705 | 1706 | - search.query_total: search에서 query를 요청한 횟수 1707 | - search.fetch_total: search에서 fetch를 요청한 횟수 1708 | - query_time_in_millis: query에 소요된 milliseconds 1709 | - fetch_time_in_millis: fetch에 소요된 milliseconds 1710 | 1711 |
1712 | 1713 | - A = 1초 전 search.query_total - 현재 search.query_total = 1초 간 search query total 건수 1714 | - 초당 search query 의 rate 1715 | - B = 1초 전 search.query_time_in_millis - 현재 search.query_time_in_millis = 1초 간 query time_in_millis 1716 | - 초당 search query 의 latency 1717 | 1718 |
1719 | 1720 | - 그외 merge, refresh등의 수치도 제공 1721 | - 위 데이터를 primaries기준, total기준으로 제공하고, 인덱스별로도 해당 데이터를 제공 1722 | 1723 |

1724 | 1725 | #### Nodes API 1726 | 1727 | - `GET _nodes` 1728 | - 각 노드의 uuid를 key로 하여 elasticsearch.yml, jvm.options, plugin 정보 등을 제공 1729 | - 노드 이름, ip 정보, es버전, 노드 roles정보 확인 가능 1730 | - elasticsearch.yml에 세팅된 정보 외에 추가정보 확인 가능 1731 | - jvm.options에 세팅된 정보 확인 가능 1732 | 1733 |
1734 | 1735 | - `GET _nodes/stats` 1736 | - \_stats에서 확인할 수 있었던 항목들을 노드별로 보여줌 1737 | - `"os"`: 노드의 시스템 지표도 함께 확인 가능 1738 | - `"jvm"`: GC에 대한 항목 확인 가능 1739 | - `"fs"`: 파일시스템 사용량 확인 가능 1740 | 1741 |




1742 | 1743 | --- 1744 | 1745 | Elasticsearch 성능 테스트 1746 | ========================= 1747 | 1748 | --- 1749 | 1750 | 성능 테스트 시나리오 1751 | -------------------- 1752 | 1753 | - ‘어떻게 해야 정확한 성능을 테스트할 수 있을까?’ 시나리오 만들기 1754 | 1755 | #### 시나리오 만들기 1756 | 1757 | - 검색 엔진 서비스는 응답 속도가 생명 1758 | - 대형 검색 서비스의 검색엔진 서비스 1759 | - 문서 웹 크롤러 -> 데이터 스토어 -> 검색엔진 인덱싱 -> 서비스 1760 | - Near-Real Time Search Engine 1761 | - ES 같이 가벼운 검색엔진은 인덱싱과 검색이 공존하는게 일반적 1762 | - es는 작게 작게 만들어서 작게 작게 서비스, 빠르게 서비스한다. 1763 | - es같이 가벼운 검색엔진같은 경우, 인덱싱도 받아가면서 서비스 해준다. 1764 | - 들어오는 데이터를 바로바로 검색결과에 노출시켜준다고 해서 Near-Real Time 1765 | - 준 실시간 검색엔진을 구성하여 서비스 한다. 1766 | 1767 | #### 준 실시간 검색엔진 만들기 시나리오 조건 1768 | 1769 | - 요구사항 1770 | 1771 | 1. 데이터는 검색이 이뤄지는 순간에도 계속 인덱싱 된다. 1772 | 2. 쿼리는 인덱스의 전체 문서를 요구할 만큼 무거운 쿼리가 들어올 수 있다. 1773 | 3. 검색 엔진의 생명은 응답속도이다. 응답 속도는 200 milliseconds이하가 나와야 한다. 1774 | 4. 검색 서비스에 사용할 인덱스의 사이즈는 200G 이다. (하루 인덱스 사이즈가 200G란 소리) 1775 | 5. 데이터는 일 단위로 교체가 필요하다. 당일 만들어진 인덱스는 23:59까지만 서비스하고 다음 날 만들어진 인덱스는 00:00부터 서비스한다. 1776 | - a. 다음 날 인덱스를 미리 만들어 둘 수 있는 경우 1777 | - b. 당일 인덱스를 만들어야하는 경우 (이런경우는 거의 없을 듯) 1778 | 1779 | - 요구사항 테스트 1780 | 1781 | 1. 데이터는 검색이 이뤄지는 순간에도 계속 인덱싱 된다. 1782 | - **인덱싱을 하면서 검색 수행** 1783 | 2. 쿼리는 인덱스의 전체 문서를 요구할 만큼 무거운 쿼리가 들어올 수 있다. 1784 | - **검색을 수행하는 쿼리를 와일드 카드로 지정** 1785 | 3. 검색 엔진의 생명은 응답속도이다. 응답 속도는 200 milliseconds이하가 나와야 한다. 1786 | - **1~2 과정을 반복하며 응답속도 확인** 1787 | 4. 검색 서비스에 사용할 인덱스의 사이즈는 200G 이다. (하루 인덱스 사이즈가 200G란 소리) 1788 | 5. 데이터는 일 단위로 교체가 필요하다. 당일 만들어진 인덱스는 23:59까지만 서비스하고 다음 날 만들어진 인덱스는 00:00부터 서비스한다. 1789 | - **alias 기능을 이용** 1790 | 6. a. 다음 날 인덱스를 미리 만들어 둘 수 있는 경우 1791 | - **인덱스를 미리 만들고 alias를 조정** 1792 | 7. b. 당일 인덱스를 만들어야하는 경우 (이런경우는 거의 없을 듯) 1793 | - **인덱스를 만들면서 alias를 조정** 1794 | 1795 | #### 검색 엔진의 성능을 결정짓는 요소 1796 | 1797 | - 각자 시스템이나 네트워크의 환경은 상이할 수 밖에 없다 1798 | - 사용자의 데이터 및 쿼리문도 전부 상이할 수 밖에 없다. 1799 | - 절대 조건은 없다. 각자의 환경에서 es의 성능을 측정해야한다. 1800 | - 검색 성능 최적화 샤드배치 결정에서 다뤘던 일반적인 내용 외에 내 검색 엔진의 성능을 측정해야 한다. 1801 | 1802 | - 검색은 query then fetch의 과정, 여러개의 노드와 여러개의 샤드가 성능을 결정 1803 | 1804 | - 지난시간까지 검색성능 최적화 샤드배치에서 다뤘던 것은 일반적인 내용, 나중에 elk클러스터 구축할때는 참고, 지금부터할것은 검색엔진을 만드는 것이니 굉장히 응답속도에 민감한 클러스터를 만든다고 생각하면 됨 1805 | 1806 |

1807 | 1808 | 성능 테스트 환경 1809 | ---------------- 1810 | 1811 | - 단일 노드에 단일 샤드 세팅 1812 | - 인덱싱과 검색이 하나의 노드, 하나의 샤드에서만 수행된다. 1813 | - 실제 검색할 데이터를 지속적으로 인덱싱 1814 | - 인덱스 크기를 지속적으로 모니터링, 인덱스의 크기가 샤드의 크기 1815 | - 실제 검색할 쿼리를 지속적으로 요청 1816 | - took속도를 지속적으로 모니터링 1817 | 1818 |

1819 | 1820 | 성능 테스트 결과 해석 1821 | --------------------- 1822 | 1823 | - 인덱싱과 검색을 계속 지속하면서 요구조건인 200ms에 수렴하는 인덱스(샤드)의 사이즈 확인 1824 | - 여기서는 10G가 나왔다고 가정 1825 | - 이때 나온 샤드의 사이즈가 인덱싱도 되고 검색도 무거운 쿼리로 요청을 받았을 최악의 경우에서 요구 조건인 200ms를 받아낼 수 있는 사이즈 1826 | - 실제 검색에서는 문서 전체가 조회되지는 않으나 이 시나리오에서는 전체 문서가 검색되는 최악의 경우 1827 | - 이때 나온 샤드의 사이즈를 검색될 인덱스 200G와 계산하여 샤드 갯수를 구함 1828 | - 200G / 10G = 20개 1829 | 1830 | . 1831 | 1832 | . 1833 | 1834 | . 1835 | 1836 | . 1837 | 1838 | . 1839 | 1840 | . 1841 | 1842 | . 1843 | 1844 | . 1845 | 1846 | . 1847 | 1848 | . 1849 | 1850 | . 1851 | 1852 | . 1853 | 1854 | . 1855 | 1856 | . 1857 | 1858 | . 1859 | 1860 | . 1861 | 1862 |




1863 | 1864 | 추가자료 1865 | ======== 1866 | 1867 | Per-License Supports 1868 | -------------------- 1869 | 1870 | - For more details on [HERE](https://www.elastic.co/subscriptions) 1871 | 1872 | 1873 | 1874 |

1875 | 1876 | About Mapping type and deprecated 1877 | --------------------------------- 1878 | 1879 | - [링크](https://www.elastic.co/guide/en/elasticsearch/reference/current/removal-of-types.html#_why_are_mapping_types_being_removed) 1880 | 1881 | ### mapping type은 무엇인가? 1882 | 1883 | - es가 릴리즈된 이래에서, 각 document는 single index에 저장되었고, single mapping type에 할당되었다. 1884 | - mapping type document의 type 또는 인덱스된 entity를 표현하는데 사용되었다. 예를들어 `twitter` index는 `user` type과 `tweet` type을 가진다. 1885 | - 각각의 mapping type은 그것들이 소유한 field를 가질 수 있고, 1886 | - `user` type은 `full_name`, `user_name` 그리고 `email` field를 가질 수 있고 1887 | - `tweet` type은 `content`, `tweeted_at` 그리고 `user_name` field(`user` type의 것과 같이) 가질 수 있다. 1888 | - 각 document는 type name을 포함하는 `_type` meta-field를 가지고, searches는 URL에 있는 type name을 명시함으로써 하나이상의 type으로 제한 될 수 있다. 1889 | 1890 | ```shell 1891 | GET twitter/user,tweet/_search 1892 | { 1893 | "query": { 1894 | "match": { 1895 | "user_name": "kimchy" 1896 | } 1897 | } 1898 | } 1899 | ``` 1900 | 1901 | - `_type` field는 `_uid` field를 생성하기 위해 document의 `_id`와 결합되고, 같은 `_id`와 함께 다른 type의 document들은 single index에 존재할 수 있다. 1902 | - mapping type은 또한 document간에 [parent-child relationship](https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-parent-field.html)을 만들수 있고, type `question`의 document들은 type `answer`의 document들의 부모일 수 있다. 1903 | 1904 |


1905 | 1906 | ### 왜 mapping type이 제거될 예정인가? 1907 | 1908 | - 일반적으로 index는 database, type은 table과 비슷하다고들 말한다. 1909 | - 그렇지만, 이건 정확한 설명이 될 수 없다. 1910 | - sql db에서 table은 서로 독립적이다. 1911 | - 한 table에 있는 column은 다른 table의 같은이름을 가진 column과 관련을 가지고 있지 않다. 1912 | - 이것은 mapping type에서 field와는 다른 경우이다. 1913 | 1914 |
1915 | 1916 | - 같은 index내에서 \_type이 다르더라도 같은 이름의 field를 갖는다면, 루신의 특징에 의해 내부적으로 하나의 field로 관리된다. 1917 | - 다른 mapping type에서 같은 이름을 가진 field들은 내부적으로 같은 루씬 field의 도움을 받는다. 1918 | - 위에서, 각각의 `user_name`field는 하나로 mapping된다. (table은 각자 따로 저장됨) 1919 | - `user` type에서 `user_name` 데이터를 바꾸거나 타입을 바꾸면, 문제가 될 수 있다. 1920 | - 공통 field가 별로 없는 데이터를 하나의 index에 넣는 것은 효율적으로 document를 압축시키지 못한다. 1921 | - 이런 이유로, elastic은 es로부터 mapping type의 컨셉을 제거하기로 결정 1922 | 1923 | 1924 | 1925 |


1926 | 1927 | ### 대처 방안 1928 | 1929 | #### 1. type별로 index생성 1930 | 1931 | - type별로 index를 생성하면, 기존의 방식보다 루신의 데이터 압축이 잘 되는 장점 1932 | - tweets와 users데이터를 `twitter` index에 저장했던거와 다르게, 각각의 인덱스에 저장 1933 | - 각각의 인덱스는 완벽하게 서로 독립적이기 때문에 인덱스간 field type의 충돌걱정은 할필요 없다. 1934 | - 두가지 benefits 1935 | - data는 루씬에서 사용된 압축기술의 장점을 얻을 수 있다. 1936 | - full-text search에서 스코어링을 위해 사용된 term관련 통계가 더 정확할 것이다. (왜냐하면 같은 index에 있는 모든 documents가 싱글 entity를 표현한다.) 1937 | 1938 | #### 2. custom type 1939 | 1940 | - 기존에 사용하던 `_type`을 사용하지 않고, 각 document별로 docType과 같이 type을 구분할 수 있는 field를 넣어준다. 1941 | -------------------------------------------------------------------------------- /pictures/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmare/es_lecture/7a64f12a982a324ae238c5e34df3fe909c56dada/pictures/.DS_Store -------------------------------------------------------------------------------- /pictures/analysis-chain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmare/es_lecture/7a64f12a982a324ae238c5e34df3fe909c56dada/pictures/analysis-chain.png -------------------------------------------------------------------------------- /pictures/close-api.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmare/es_lecture/7a64f12a982a324ae238c5e34df3fe909c56dada/pictures/close-api.png -------------------------------------------------------------------------------- /pictures/doc-search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmare/es_lecture/7a64f12a982a324ae238c5e34df3fe909c56dada/pictures/doc-search.png -------------------------------------------------------------------------------- /pictures/elk_stack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmare/es_lecture/7a64f12a982a324ae238c5e34df3fe909c56dada/pictures/elk_stack.png -------------------------------------------------------------------------------- /pictures/es-cluster-structure1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmare/es_lecture/7a64f12a982a324ae238c5e34df3fe909c56dada/pictures/es-cluster-structure1.png -------------------------------------------------------------------------------- /pictures/es-cluster-structure2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmare/es_lecture/7a64f12a982a324ae238c5e34df3fe909c56dada/pictures/es-cluster-structure2.png -------------------------------------------------------------------------------- /pictures/es-data-structure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmare/es_lecture/7a64f12a982a324ae238c5e34df3fe909c56dada/pictures/es-data-structure.png -------------------------------------------------------------------------------- /pictures/index-writing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmare/es_lecture/7a64f12a982a324ae238c5e34df3fe909c56dada/pictures/index-writing.png -------------------------------------------------------------------------------- /pictures/inverted_index.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmare/es_lecture/7a64f12a982a324ae238c5e34df3fe909c56dada/pictures/inverted_index.png -------------------------------------------------------------------------------- /pictures/master-fault.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmare/es_lecture/7a64f12a982a324ae238c5e34df3fe909c56dada/pictures/master-fault.png -------------------------------------------------------------------------------- /pictures/option-by-license.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmare/es_lecture/7a64f12a982a324ae238c5e34df3fe909c56dada/pictures/option-by-license.png -------------------------------------------------------------------------------- /pictures/remove-multipath01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmare/es_lecture/7a64f12a982a324ae238c5e34df3fe909c56dada/pictures/remove-multipath01.png -------------------------------------------------------------------------------- /pictures/remove-multipath02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmare/es_lecture/7a64f12a982a324ae238c5e34df3fe909c56dada/pictures/remove-multipath02.png -------------------------------------------------------------------------------- /pictures/remove-multipath03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmare/es_lecture/7a64f12a982a324ae238c5e34df3fe909c56dada/pictures/remove-multipath03.png -------------------------------------------------------------------------------- /pictures/rolling-restart01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmare/es_lecture/7a64f12a982a324ae238c5e34df3fe909c56dada/pictures/rolling-restart01.png -------------------------------------------------------------------------------- /pictures/rolling-restart02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmare/es_lecture/7a64f12a982a324ae238c5e34df3fe909c56dada/pictures/rolling-restart02.png -------------------------------------------------------------------------------- /pictures/rolling-restart03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmare/es_lecture/7a64f12a982a324ae238c5e34df3fe909c56dada/pictures/rolling-restart03.png -------------------------------------------------------------------------------- /pictures/rolling-restart04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmare/es_lecture/7a64f12a982a324ae238c5e34df3fe909c56dada/pictures/rolling-restart04.png -------------------------------------------------------------------------------- /pictures/search_fetch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmare/es_lecture/7a64f12a982a324ae238c5e34df3fe909c56dada/pictures/search_fetch.png -------------------------------------------------------------------------------- /pictures/search_query.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmare/es_lecture/7a64f12a982a324ae238c5e34df3fe909c56dada/pictures/search_query.png -------------------------------------------------------------------------------- /pictures/shard-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmare/es_lecture/7a64f12a982a324ae238c5e34df3fe909c56dada/pictures/shard-1.png -------------------------------------------------------------------------------- /pictures/shard-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmare/es_lecture/7a64f12a982a324ae238c5e34df3fe909c56dada/pictures/shard-2.png -------------------------------------------------------------------------------- /pictures/shard-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmare/es_lecture/7a64f12a982a324ae238c5e34df3fe909c56dada/pictures/shard-3.png -------------------------------------------------------------------------------- /pictures/shard-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmare/es_lecture/7a64f12a982a324ae238c5e34df3fe909c56dada/pictures/shard-4.png -------------------------------------------------------------------------------- /pictures/shard-allocation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmare/es_lecture/7a64f12a982a324ae238c5e34df3fe909c56dada/pictures/shard-allocation.png -------------------------------------------------------------------------------- /pictures/split-brain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmare/es_lecture/7a64f12a982a324ae238c5e34df3fe909c56dada/pictures/split-brain.png -------------------------------------------------------------------------------- /pictures/term-index.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmare/es_lecture/7a64f12a982a324ae238c5e34df3fe909c56dada/pictures/term-index.png -------------------------------------------------------------------------------- /pictures/term-type.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmare/es_lecture/7a64f12a982a324ae238c5e34df3fe909c56dada/pictures/term-type.png -------------------------------------------------------------------------------- /pictures/type-deprecated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmare/es_lecture/7a64f12a982a324ae238c5e34df3fe909c56dada/pictures/type-deprecated.png --------------------------------------------------------------------------------