클러스터와 노드의 개념

  • 클러스터: 여러 대의 컴퓨터 혹은 구성 요소들을 논리적으로 결합하여 전체를 하나의 컴퓨터, 혹은 하나의 구성 요소처럼 사용할 수 있게 해주는 기술
  • ElastSearch 클러스터 역시 여러 개의 ElasticSearch 프로세스들을 논리적으로 결합하여 하나의 ElasticSearch 프로세스철머 사용할 수 있게 해준다.
    • 다수의 노드로 클러스터를 구성하면 하나의 노드에 장애가 발생해도 다른 노드에 요청할 수 있기 때문에 안정적으로 클러스터를 유지할 수 있고 이를 통해서 높은 수준의 안정성을 보장할 수 있다.
  • 다수의 노드로 구성된 ElasticSearch 클러스터는 고유의 클러스터 이름과 UUID를 가진다.
    • 1: 노드의 이름.
    • 2: 클러스터 이름. 클러스터에 속한 모든 노드들은 클러스터 이름이 같다.
    • 3: 클러스터의 UUID. 클러스터에 속한 모든 노드가 동일한 값을 가진다.
  • 노드의 역할
    • 마스터 노드: 클러스터 구성에서 중심이 되는 노드. 클러스터의 상태 등 메타데이터를 관리한다.
      • 클러스터의 메타데이터를 관리
      • 클러스터 내의 모든 노드는 현재 노드의 상태, 성능 정보, 자신이 가지고 있는 샤드의 정보를 마스터 노드에 알린다.
      • 하나의 노드만 마스터 노드로 동작하고, 나머지는 마스터 후보 노드가 되어 지속적으로 클러스터 운영에 필요한 케타 데이터를 전달받아 유지한다.
        • 마스터 노드에 장애 발생해서 새로운 마스터 노드가 선출되어도 중단 없이 서비스를 이어갈 수 있다.
    • 데이터 노드: 사용자의 문서를 실제로 저장하는 노드.
      • 사용자가 색인한 문서를 저장하고, 검색 요청을 처리해서 결과를 돌려주는 역할.
      • 자신이 받은 요청 중 자신이 처리할 수 있는 요청은 직접 처리하고, 다른 데이터 노드들이 처리해야 할 요청은 해당 데이터 노드에 전달한다.
        • 이 때 어떤 데이터 노드로 요청을 보낼 것인지는 마스터 노드를 통해 받은 클러스터의 전체 상태 정보를 바탕으로 한다.
    • 인제스트 노드: 사용자의 문서가 저장되기 전 문서 내용을 사전 처리하는 노드.
      • 데이터 노드에 저장하기 전에 특정 필드의 값을 가공해야 할 경우 유용하게 동작한다.
    • 코디네이트 노드: 사용자의 요청을 데이터 노드로 전달하고, 다시 데이터 노드로부터 결과를 취합하는 노드.
      • 실제 데이터를 저장하고 처리하지는 않지만, 사용자의 색인이나 검색 등 모든 요청을 데이터 노드에 전달하는 역할을 한다.

인덱스와 타입

  • 인덱스는 사용자의 데이터가 저장되는 논리적인 공간을 의미하며 타입은 인덱스 안의 데이터를 유형별로 논리적으로 나눠 놓은 공간을 의미한다.
  • 보통 인덱스와 티입에 대해 이야기할 때 RDMBS와 비교하기도 한다.
  • 서로 다른 형태의 JSON 문서를 가진다면 인덱스를 분리하는 것이 좋다.
  • 인덱스에 저장된 문서들은 데이터 노드들에 분산 저장된다.

샤드와 세그먼트

  • 샤드: 인덱스에 색인 되는 문서들이 저장되는 논리적인 공간
  • 세그먼트: 샤드의 데이터를 가지고 있는 물리적인 파일
  • 하나의 인덱스는 다수의 샤드로 구성되고 하나의 샤드는 다수의 세그먼트로 구성된다.
    • 샤드는 1개 이상의 세그먼트로 구성되는데 샤드마다 세그먼트의 개수는 서로 다를 수 있다.
  • 프라이머리 샤드는 최초 인덱스를 생성할 때 개수를 결정하는데, 이때 결정한 프라이머리 샤드의 개수는 이후에 변경할 수 없다. 따라서 인덱스를 생성할 때 신중하게 결정해야 한다.
  • 인덱스에 저장되는 문서는 해시 알고리즘에 의해 샤드들에 분산 저장되고 이 문서들은 실제로는 세그먼트라는 물리적 파일에 저장된다.
    • 문서가 처음부터 세그먼트에 저장되는 것은 아니다.
    • 색인된 문서는 먼저 시스템의 메모리 버퍼 캐시에 저장되는데 이 단계에서는 해당 문서가 검색되지 않는다.
    • 이후 ElastSearch의 refresh 과정을 거쳐야 디스크에 세그먼트 단위로 문서가 저장되고 해장 문서의 검색이 가능해진다.
  • 세그먼트는 불변의 특성을 갖는다. 즉, 기존에 기록한 데이터를 업데이트하지 않는다.
    • 문서 업데이트 요청이 오면, 새로운 세그먼트에 업데이트할 문서의 내용을 버전을 증가하여 새롭게 쓰고, 기존 데이터는 더 이상 쓰지 못하도록 불용 처리한다.
  • 이렇게 세그먼트 단위로 파일을 생성해서 문서를 저장할 때, 불변의 특성을 유지하기 위해 여러 개의 세그먼트로 사용자의 문서를 색인하는데, 시간이 지나면 작은 크기의 세그먼트가 점점 늘아니고, 사용자가 문서를 검색할 때마다 많은 수의 세그먼트들이 응답해야 한다는 단점이 생긴다.
    • 이러한 단점을 보완하기 위해 ElasticSearchs는 백그라운드에서 세그먼트 병합(merge)을 진행한다.
    • 아래 그림과 같이 삭제 플래그가 켜진 문서는 제외하고 병합한다.
  • 이렇게 세그먼트를 병합하면 사용자의 검색 요청시 접근해야 하는 파일의 개수가 줄어들어 사용자의 요청에 그만큼 적은 비용으로 빠르게 응답할 수 있다.

프라이머리 샤드와 레플리카 샤드

  • ElasticSearch가 장애 상황에서도 데이터가 유실되지 않도록 관리하기 위해 프라이머리 샤드와 레플리카 샤드로 나눠서 관리한다.
  • 레플리카 샤드는 프라이머리 샤드와 동일한 문서를 가지고 있기 때문에 사용자의 검색 요청에도 응답할 수 있다.
    • 따라서 레플리카 샤드를 늘리면 검색 요청에 대한 응답 속도를 높일 수 있다.
  • ElasticSearch가 문서를 색인할 때 어떤 번호의 프라이머리 샤드에 문서를 저장할지 결정하는 알고리즘
    • 프라이머리 샤드 번호 = Hash(문서의 id) % 프라이머리 샤드 개수
  • 레플리카 샤드는 데이터 노드별로 원본과 복제본 샤드의 번호가 중복되지 않도록 할당된다.
  • 사용자가 설정하지 않으면 각 프라이머리 샤드당 하나의 레플리카 샤드를 만드는 것이 기본 설정이다.
  • 프라이머리 샤드는 처음에 인덱스를 생성할 때 설정하면 변경할 수 없지만, 복제본인 레플리카 샤드는 운영 중에도 샤드 개수를 변경할 수 있다.

매핑

  • 매핑: RDBMS와 비교하자면 스키마와 유사하다.
    • ElasticSearch에 저장될 JSON 문서들이 어떤 키와 어떤 형태의 값을 가지고 있는지 정의한 것이다.
    • 1: mapping API를 활용하여 인덱스의 매핑 정보를 확인할 수 있다.
    • 2: mappings 필드에 타입의 이름이 나온다. 그리고 그후 properties 필드 아래에 매핑 정보가 나온다. 여기서는 _doc이라는 타입이 있는 것을 볼 수 있다.
    • 3: account_number라는 필드는 long 데이터 타입으로 정의해 놓은 것을 볼 수 있다.
    • 4: 문자열이 저장된 필드는 text 데이터 타입으로 매핑되었다.
    • 5: 4와 함께 keyword 데이터 타입의 매핑이 추가로 생성되었다.