현재 나는 백엔드 조회/검색 성능 최적화 작업을 진행중이다. (기간 : 11월 4일 ~ 12월 2일)
최종목표는, 대용량 데이터 핸들링 속도를 최적화하는 것이며, 목표 데이터수는 최소 600만건을 목표로 잡고있다.
이를 위한 첫번째로, 검색기능에 querydsl의 동적쿼리를 사용하며 fetch join / 페이징기법 / dto 프로젝션반환 등등을 시도 중에 있다.
헌데 속도가 그리 뛰어나지 않은 상태이다. 현재 위 사항들을 적용한 결과 검색결과 반환시간이 최소 7분이다.
이를 해소시키기 위해 검색기능에 특화된 Elasticsearch를 도입하고자하며, 도입시키기 이전에 개념에 대한 부분을 정리하고자 한다.
Elasticsearch
> 아파치 루씬 기반으로 만들어진 기능이다 (루씬 기능 대부분을 지원한다)
루씬의 특징
1. 자바언어로 개발됨
2. 다국어 검색지원
3. 사용자 위치정보 이용가능
4. 자동완성 지원
5. 미리보기 지원
6. 철자 수정기능 지원
elasticsearch는 분산시스템이다.
1. 엘라스틱 서치는 여러 개의 노드로 구성된 분산 시스템이다.
2. 노드는 데이터를 색인하고 검색을 수행하는 단위 프로세스다.
3. 기존 노드에서 새 노드를 실행하여 연결하는 것만으로 확장이 가능하다.
4. 데이터는 각 노드에 분산 저장된다.
5. 복사본을 유지하여 각종 충돌로부터 노드 데이터를 보호한다.
[추가정보]
RDBMS와 elasticsearch차이점
> RDBMS
데이터를 테이블 형태로 저장한다.
> elasticsearch
inverted index라는 구조로 저장한다.
텍스트를 모두 뜯어서 검색어 사전형태로 만든다.
마치 책의 맨뒤에 있는 페이지를 가리키는 키워드와 같다.
elasticsearch 요소
1. 클러스터 (cluster)
하나 이상의 노드(서버)가 모인 것이며, 이를 통해 전체데이터를 저장하고 모든 노드를 포괄하는 통합 색인화 및 검색기능을 제공한다.
클러스터는 고유한 이름으로 식별되는데, 기본 이름은 eleasticsearch이다.
2. 노드 (node)
클러스터에 포함된 단일 서버로서, 데이터를 저장하고 클러스터의 색인화 및 검색기능에 참여한다.
노드는 클러스터처럼 이름으로 식별되는데, 기본이름은 시작 시 노드에 지정되는 임의 UUID이다.
기본이름 대신 특정 이름으로 정의 가능하다.
또한 노드는 마스터노드 / 데이터노드로 구분된다.
마스터노드 (master node)
전체 클러스터 상태의 메타정보를 관리, 종료되는 경우 새로운 마스터 노드가 선출됨
데이터노드(data node)
실제 데이터가 저장되는 노드
3. 샤드 (shard)
데이터 검색을 위해 구분되는 최소단위
색인된 데이터는 여러개의 샤드로 분할돼 노드에 저장된다.
데이터가 색인돼 저장되는 공간을 최초샤드 (primary shard)라 한다.
최초 샤드에 데이터가 색인되면 동일한 수만큼 복사본을 생성한다.
최초 샤드가 유실될 경우, 복사본을 최초 샤드로 승격시킨다.
최초 샤드와 복사본은 동시 검색대상이 되어 성능 향상에 이점이 있다.
최초 샤드와 복사본은 서로 다른 노드에 저장된다.
elasticsearch 작업단계
1. 대용량 검색을 위한 클러스터링 과정
1. 데이터를 샤드 단위로 분리하여 저장한다.
2. 노드를 여러개 실행시키면 같은 클러스터로 묶는다.
3. 샤드들은 각각의 노드에 분배되어 저장된다.
4. 무결성과 가용성을 위해 샤드의 복제본을 만든다. 같은 내용의 샤드와 복제본은 서로 다른 노드에 저장.
5. 시스템 다운이나 네트워크 단정 등으로 유실된 노드가 생기면
복제본이 없는 샤드들은 다른 살아있는 노드로 복제를 시작한다.
그럼으로써, 노드의 수가 줄어들어도 샤드의 수는 변함없이 무결성을 유지한다.
2. 검색과정 - Query Phase
1. 처음 쿼리 수행 명령을 받은 노드는 모든 샤드에게 쿼리를 전달한다.
1차적으로 모든 샤드(또는 복제본에서) 검색을 실행한다.
2. "from+size" 크기의 결과 큐를 처음 명령 받은 노드로 리턴한다.
리턴된 결과는 루씬 doc id와 랭킹 점수만 가지고 있다.
노드는 리턴된 결과들을 가지고 랭킹 점수 기반으로 정렬한다.
그 후, 정렬된 값 기반으로 유효한 샤드들에 검색 결과들을 요청한다.
마지막으로, 전체 문서내용 (_source) 등의 정보가 리턴되어 클라이언트로 전달된다.
elasticsearch 핵심
검색엔진에서는 정확한 검색을 위한 랭킹 알고리즘이 매우 중요하다.
TF/IDF는 별도로 알아보자
'Spring' 카테고리의 다른 글
페치조인 (Fetch Join) (0) | 2022.11.07 |
---|---|
JOIN종류 / ON절의 의미 / Query 조회기능 최적화 팁 (0) | 2022.11.07 |
ExceptionHandler / ControllerAdvice 사용법 (0) | 2022.11.03 |
WebSocket / STOMP (1) | 2022.10.28 |
querydsl 사용법! (0) | 2022.10.27 |
댓글