- 토스에서는 하루 170억건의 로그를 인덱싱한다. 서비스가 커질수록 로그는 늘어나기 때문에 수평적으로 확장하고 안정적으로 운영하기 위해 지속적으로 클러스터 개선이 필요하였다.
- ES 클러스터는 온프레미스로 운영하고 있어 공간과 관리 부담이 있기 때문에
Hot - Warm 아키텍처
를 도입 - Hot 노드보다 더 큰 디스크를 가진 Warm 노드를 구성 후, 생성된지 오래된 인덱스는 Warm 노드로 이동하고 일정 기간이 지나면 삭제하도록 ILM (Index Lifecycle Management) 구성
- 클러스터가 크레 느려졌을 때 노드들의 상태는 공통적안 패턴이 있었는데, fielddata가 매우 많은 메모리를 사용하고 있었고, 그로인해 GC가 빈번하게 발생하여 클러스터가 일시적으로 멈추는 현상이 존재하였다.
- 장애 당시 설정에는 fielddata 옵션이 설정되어 있었는데 유입되는 로그의 양이 매우 많다보니 힙 메모리가 금방 가득차고 길고 빈번하게 GC가 발생
- ES 및 루씬에 Doc value가 도입되기 전에는 필드에 대해서 aggregation과 정렬을 하기 위해 필드의 값들을 fielddata라는 메모리 영역으로 올려서 수행하였다.
- 그러다보니 힙 메모리가 부족해지고 긴 GC가 발생하여 클러스터가 일시적으로 멈추는 현상이 빈번했다.
- 그래서 ES는 파일 시스템을 사용하고, 컬럼 기반인 Doc value storage를 도입하여 힙메모리를 덜 사용하도록 하고 OS leve cache를 사용하는 방향으로 발전하였다.
- Doc value 스토리지를 지원하는 지금은 특별한 경우가 아니면 fielddata를 사용할 일이 없다.
- Doc value 스토리지를 지원하지 않는 text 타입을 aggregation 하려는 목적에서는 fielddata를 사용할 수는 있지만 가급적 사용하지 말고 다른 방법으로 해결하는 것이 좋다.
- 유입되는 로그가 많아지고 커질수록 인덱스 매핑도 중요하다. 안정적인 클러스터를 운영하려면 인덱스 필드를 제어할 수 있어야 한다.
- 만약 클러스터가 느려지고 불안정한 경우, 원인을 분석하면 대부분 인덱스 매핑이 비효율적으로 되어있는 경우가 많다.
- 만약 관리하고 있는 ES 클러스터가 느러지고 불안정하다면 맨 먼저 인덱스 매핑을 살펴보자.
- 인덱스에 너무 많은 필드들이 매핑되어있는지
- fielddata 옵션을 사용하는 필드가 있는지
- default dynamic mapping을 사용하고 있는지
- 명시적인 설정을 하지 않으면 json 형태 그대로 동적으로 인덱스 매핑을 업데이트 한다. (default dynamic mapping)
- 이런 특성으로 인해 유입되는 json에 key가 매우 많거나 비규칙적이라면 인덱스 매핑이 일어나게 되고 리소스를 사용하게되어 클러스터가 불안정하게 된다.
- 인덱싱할 데이터가 너무 많은 키를 가지지 않도록 하면 좋다.
- 어쩔수 없이 임의의 구조를 가진 데이터를 인덱싱 해야한다면, flattened type을 사용하거나 dynamic field 옵션을 false로 설정하여 명시적으로 매핑한 필드만 인덱싱 되게 한다.
- 샤드 수를 결정하는데 정답은 없다.
- 토스증권에서는 경우에 따라 프라이머리 샤드의 갯수는 Hot 노드의 수와 동일하게 하고있다.
- 노드의 CPU 사용량 여유가 있다면 프라이머리 샤드 갯수를 더 늘려서 초당 인덱싱 처리량을 개선하면 좋다.
- 다만 프라이머리 샤드를 더 늘린다면 샤드가 특정 노드에 쏠려 핫스팟 노드가 될 수 있기 때문에 샤드의 수를 Hot 노드의 배수로 설정하는 것이 좋다.
- => [TODO] 이 부분은 따로 공부해볼 것
- index_refesh-time = 60s 로 설정하여 세그먼트 생성과 머지가 적게 발생하도록 하여속
- flush_threshold_size 는 기본값인 512MB에서 두배인 1GB 설정하여 트랜스로그 플러시를 실행하는 빈도를 낮추도록 하였다.
- => [TODO] 이부분도 따로 공부해볼 것