├── 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가 적용(언어 문법 기준 파싱) 
1135 | - 1. 문서가 들어오면 analyzer가 용어별로 나열
1136 | - 2. 용어가 몇번 들어왔는데 갯수 정리
1137 | - 3. 용어가 몇번 문서에 있는지 metadata형태로 저장
1138 | - 4. 세그먼트 저장되기 전에 버퍼에 저장되어있다가 리프래쉬되면 세그먼트에 쓰여진다.
1139 | - 한줄요약: analyzer가 문서가 들어오면 문서를 쪼개서 inverted index형태로 만든 후에 세그먼트로 저장
1140 |
1141 | ### 분석기 변경 방법
1142 |
1143 | - Analysis
1144 |
1145 | - text에 대해 검색이 될 수 있도록 분석하는 과정
1146 |
1147 | 
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 | 
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 | 
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
--------------------------------------------------------------------------------