Elasticsearch in action (~ 138p)

1장 일래스틱서치 소개

  • 일래스틱서치는 오픈소스 검색 라이브러리 아파치 루씬을 기반으로 만들었다.
    • 루씬은 자바 애플리케이션에 검색 기능을 구현할 수 있게 해준다.
    • 루씬은 역 색인(inverted indexing)을 사용한다.
  • 일래스틱서치 클러스터를 색인, 검색, 관리하기 위해 데이터를 JSON 형태로 HTTP를 통해 전달할 수 있다.

  • rawdata

    ID 태그
    1 투표
    2 평화
    3 투표, 평화
    4 평화
  • 색인 데이터

    태그 ID
    투표 1, 3
    평화 2, 3, 4

관련 결과 보장

  • 관련성 점수(relevancy score)
    • 검색조건과 일치하는 각각의 문서에 할당된 점수
    • 문서가 얼마나 조건과 관련성이 있는지
    • 검색어가 좀 더 많이 존재하면 대개 그 문서에 더 높은 순위를 매긴다.
    • 관련성 점수를 평가하는 데 사용하는 알고리즘은 tf-idf
      • 단어빈도 - 역문서빈도 를 나타낸다.
        • 관련성 점수에 영향을 주는 두 요소
        • 단어빈도 (term frequency) : 문서에서 찾고자 하는 단어가 많이 나올수록 높은 점수
        • 역 문서 빈도(inverse document frequency) : 단어가 다른 문서들 간에 흔치 않으면 각 단어의 가중치가 높다

완전 일치를 뛰어넘어 검색하기

  • 오타 처리
  • 파생어 지원
  • 통계 사용
  • 제안 제공

일래스틱서치 사용사례

  • 기본값으로 클러스터링 할 수 있어서 하나의 서버에서 실행할 때도 클러스터라고 부른다.

일래스틱서치에서 데이터 구조화하기

  • 일래스틱서치에서는 문서가 계층적일 수 있다.

2장 기능 들여다보기

논리적인 배치 이해하기: 문서, 타입, 색인

  • 문서의 색인을 만들 때 색인 안의 타입에 문서를 넣는다.
    • 색인 엄청 어색하다 인덱스가 번역되어 버려서..
  • 색인-타입-ID 조합은 ES 에서 하나의 문서를 유일하게 식별한다.
    • 검색할 때 특정 색인의 특정 타입에서 문서를 찾거나, 여러 타입 혹은 여러 색인에 걸쳐 검색할 수 있다.
  • ES가 문서 기반이라고 했는데, 색인과 검색하는 데이터의 가장 작은 단위가 문서라는 것을 의미한다.

문서

  • 독립적이다. 문서는 필드(name)와 값(ES Denver)을 가지고 있다.
  • 계층을 가질 수 있다. (문서 안의 문서)
  • 유연한 구조로 되어 있다. 즉 미리 정의한 스키마에 의존하지 않는다.
  • 문서는 보통 JSON 표현
  • 필드를 추가하거나 생략할 수 있지만, 필드의 타입은 중요하다.

타입

  • 문서에 대한 논리적인 컨테이너
  • 각 타입에서 필드의 정의는 매핑이라고 부른다.
  • 새로운 문서가 매핑에 존재하지 않는 필드와 함께 색인하면, ES는 자동으로 새로운 필드를 매핑에 추가한다.
    • 필드를 추가하기 위해 타입을 추측한다.
    • 원하는 타입으로 동작하지 않을 수 있다.
    • 데이터의 색인을 만들기 전에 매핑을 정의하는 것이 안전하다.

색인

  • 색인은 매핑 타입의 컨테이너다.
  • 색인은 독립적인 문서 덩어리다.
  • 각각의 색인은 디스크에 같은 파일 집합으로 저장한다.
  • 모든 매핑 타입의 모든 필드를 저장하고 고유의 설정을 한다.
  • 각 색인은 refresh_interval 이라는 설정으로 새로 색인한 문서를 검색할 수 있도록 하는 간격을 정의한다. (기본값은 1초에 한번)
    • 준 실시간 (near-real-time)

물리적 배치 이해하기: 노드와 샤드

  • 예) 각 색인은 다섯 개의 주 샤드로 구성되고, 각각은 하나의 복제를 가지고 있어서 총 10개의 샤드 가지게 됨
  • 기술적으로 샤드는 루씬이 여러분의 색인에 대한 데이터를 저장하는 파일들의 디렉토리
  • 샤드는 또한 ES가 노드에서 노드로 옮기는 가장 작은 단위이다.
  • 노드가 충분히 빨라 서로 간에 통신을 할 수 있도록 보장해야한다.
    • 스플릿 브레인(split brain) 을 방지하기 위해.
      • 클러스터의 두 파트가 통신할 수 없어 다른 파트가 떨어져 나갔다고 생각하는 것.

문서의 색인을 만들 때 무슨 일이 일어나는가?

  • 우선 문서 ID의 해시값에 기반을 둬서 선택한 주 샤드 중 하나에 보낸다.
  • 그 다음 문서는 주 샤드의 모든 복제에 색인하도록 보내진다.
    • 복제가 주 샤드로부터 데이터 동기화 유지
    • 동기된 복제는 검색을 제공하고, 주 샤드가 이용 불가한 경우 주 샤드로 자동 승격될 수 있다.

색인을 검색할 때 무슨일이 일어나는가?

  • 색인 검색 시, ES는 해당 색인의 전체 샤드를 찾아야 한다.
  • 검색하는 색인의 주 샤드와 레플리카 샤드 간에 검색 로드를 분배해서, 검색 성능과 고장 감내(fault tolerance)에 유용하게 레플리카를 사용

주 샤드와 레플리카 샤드 이해하기

  • 하나의 샤드는 하나의 루씬 색인이다.
  • 루씬 색인은 역 색인을 포함하는 파일들의 모음이다.
    • 역 색인은 ES가 전체 문서를 찾지 않고도, 하나의 텀(단어)을 포함하는 문서를 찾도록 해주는 구조
    • 기본 값으로 원문서의 내용과 검색하는 데 도움을 주는 단어사전과 단어 빈도 같은 추가 정보를 저장한다.
  • ES 색인은 하나 이상의 주 샤드와 0개 이상의 레플리카 샤드로 구성된다.
  • 레플리카는 실행 시간에 추가나 삭제할 수 있지만 주 샤드는 그렇지 않다.
    • 색인을 생성하기 전에 샤드의 수를 결정해야 한다.
    • 너무 적은 샤드는 확장에 제한하고, 너무 많은 샤드는 성능에 영향을 준다.
  • 검색요청은 전체 데이터를 포함한 주/레플리카 샤드에 전달된다. 그 후에 결과를 집계하여 클라이언트에게 보낸다.

실습

  • Windows 에서 안되던게 Mac 으로 뚝딱 된다. Mac 짱짱
    • install
        brew install elasticsearch
      
    • run
        elasticsearch
      
    • get-together index 의 group type 문서를 올려보기
        curl -X PUT 'localhost:9200/get-together/group/1?pretty' \
            -H 'Content-Type: application/json;charset=UTF-8' \
            -d ' {
                "name": "Elasticsearch Denver",
                "organizer": "Lee"
                }'
      
    • new-index 인덱스 생성해보기
        curl -H 'Content-Type: application/json;charset=UTF-8' \
            -X PUT 'localhost:9200/new-index'
      
    • https://github.com/dakrone/elasticsearch-in-action -> clone -> ./populate.sh
      • 문제가 있네, es 버전이 달라서 신 버전부터는 String type 이 없어지고 text/keyword 타입으로 나누어졌고
      • curl 요청 시 header 를 더 명확히 전달해야해서 sh 파일이 정상적으로 동작하지 않음
    • 데이터 검색 시 쿼리는 q=name:elasticsearch 처럼 특정 필드에 수행하지만, 모든 필드 검색을 원하는 경우 명시하지 않아도 된다.
      • 이럴 경우 _all이라는 특정필드를 사용한다
    • 타입을 지정할 수도 있다. 아래에선 group과 event type 만 검색하겠다는 것
        curl "localhost:9200/get-together/group,event/_search?q=elasticsearch&pretty"
      
    • 모든 인덱스에서 검색하려면 색인명을 생략하는 것도 가능하다.
    • 검색 응답은 검색 기준 일치하는 문서 뿐 아니라, 검색 성능이나 결과의 유사도를 확인하는 데 유용한 정보를 포함한다.
        {
            "took" : 2          
            "timed_out": false
            // 요청이 얼마나 걸리고 타임아웃 발생여부
                  
            "_shards" : {
                "total" : 2,
                "successful" : 2,
                "failed" 0
            }
            // 몇 개의 샤드에 질의했는지
      
            "hit" : {
                "total" : 2  // 일치하는 문서 수
                "max_score" : 0.9066504, // 일치하는 문서의 최대 점수
                // 일치하는 모든 문서에 대한 통계
      
                "hits" : { ... // 결과배열
            }
        }
      
    • 전체 문서 수는 응답에서 보는 문서 수와 일치하지 않을 수도 있다. (결과 수가 10으로 limit 걸려있어서)
    • hits 는 응답에서 보통 가장 관심있는 정보
        "hits" : [ {
            "_index" : "get-together",
            "_type" : "group",
            "_id" : "3",
            "_score" : 0.9066504,
            "fields" : {
                "location" : ["San Francisco, California, "USA"],
                "name" : ["Elasticsearch San Francisco"]
            }
        }]
      
      • 어떤 필드를 원하는지 명시하지 않으면 _source 필드가 보인다
    • 적절한 쿼리타입 선택
      • 다양한 다른 형태의 쿼리가 존재한다.
      • 쿼리는 결과를 돌려주고 각 결과는 점수가 있다.
      • 점수에 관심이 없다면, 필터 쿼리를 대신 실행할 수 있다.
        • 오직 결과가 검색과 일치하는지만 관심
      • 텀 쿼리
        • 명시한 필드에 나타난 텀별 수치를 보여준다.
            "aggregations" : {
            "organizers" : {
                "terms" : { "field" : "organizer" }
            }
            }
          
        • terms 타입 요청, organizer 필드를 찾는 organizers 라고 명명된 집계를 주세요.

es 설정하기

  • elasticsearch.yml
    • 일래스틱 특유의 옵션이 들어가는 주 설정 파일
      • 클러스터 이름 명시 등..
  • logging.yml
    • 로깅 옵션 수정
  • elasticsearch.in.sh
    • es 를 작동시키는 jvm 설정
      • 메모리 설정 조정 등
  • es 로그 엔트리는 세 가지 파일 형태로 구성된다.
    • 메인 로그(cluster-name.log)
    • 느린 검색 로그(cluster-name_index_search_slowlog.log)
      • 기본 설정은 0.5초 이상
    • 느린 색인 로그(cluster-name_index_indexing_slowlog.log)
      • 색인 작업이 0.5초 이상

클래스터에 노드 추가하기

  • /_cat/shards?v
    • like inux top

3장 데이터 색인, 변경, 삭제

  • 필드
    • _timestamp 처럼 새 데이터를 자동으로 도큐먼트에 추가하도록 설정하거나, _ttl 필드를 사용하여 지정된 시간 이후 자동삭제하게끔 할 수 있음
  • 도큐면트 변경 시 동시성 문제 관련된 것을 살펴볼 것이다.

도큐먼트 종류를 정의하는 매핑 사용하기

  • 색인은 타입을 포함하고, 타입은 개별 다큐먼트를 포함한다.
  • 다른 다큐먼트라도 같은 필드를 갖는다면 타입이 같은게 좋다.
  • GET /_mapping 을 활용하여 타입의 매핑을 확인할 수 있다.
  • PUT /_mapping 을 활용하여 타입의 매핑을 설정할 수 있다.
  • 이미 존재하는 필드 데이터 타입은 변경할 수 없다.
    • 타입의 데이터를 모두 삭제하고, 새 매핑을 입력한 후 데이터 전체를 다시 색인하게 할 수도 있다.

기본 타입

  • 문자열, 숫자, 날짜, 불린
      PUT /get-together/new-events/1 -d {
          "name": "Late Night with Elasticsearch"
          "date": "2013-10-25T19:00"
      }
    
    • “Late Night with Elasticsearch” 색인 시, 기본 분석기는 모든 문자를 소문자로 만들고 문자열을 단어 단위로 분할한다.
    • late, night, with, elasticsearch 4가지 텀을 만들어낸다.
      • 텀은 text로 부터 나온 단어이고, 검색을 위한 기본 단위
  • 매핑에서 분석을 위한 다수의 옵션을 지정할 수 있다.
    • 예를 들어, 원본 텀의 동의어 텀을 만들어내는 분석도 설정할 수 있다.
        PUT /get-together/_mapping/new-events -d {
        ...
        "name": {
            "type: "string",
            "index": "not_analyzed"
        }
        }
      
    • index 기본 값은 analyzed 인데 이렇게하면 전체 문자를 단일 텀으로 인식하는 것.
    • index 를 no 로 설정하면 검색이 아예 안됨
      • 검색이 필요없는 필드에 이렇게 설정하면 되겠지?
  • 날짜 타입은 long 숫자로 루씬 색인에 저장함
    • UTC 1970 1 1 00:00:00 부터 지정시간까지 ms 숫자로 저장함
  • 문자열을 위한 다중 필드
      PUT /blog/_mapping/posts -d {
          "properties": {
              "tags": {
                  "type": "string",
                  "index": "analyzed",
                  "fields": {             // 두번째 필드 정의
                      "verbatim": {
                          "type": "string",
                          "index": "not_analyzed"
                      }
                  }
              }
          }
      }
    

사전 정의 필드

  • 특수 기능을 갖고있다.
    • e.g. _ttl 필드는 특정 시간 이후에 도큐먼트 자동 삭제 기능
  • 필드 이름이 모두 언더스코어(_)로 시작한다.
  • _source 는 모든것을 저장하고 _all 는 모든것을 색인한다.
  • _uid 를 내부적으로 사용하고 다른구조로 사용하기 쉽도록 _type과 _id라는 추상적인 개념으로 분리하여 제공한다.

기존 도큐먼트 변경하기

  • 조회 - 처리 - 재색인을 수반한다.
  • 존재하지 않는 도큐먼트를 생성할 때는 upsert
  • 동시에 다수 변경을 실행한다면 동시성 문제가 발생할 수 있다.

데이터 삭제하기

  • 삭제 방법
    • 개별 도큐먼트 또는 도큐먼트 그룹 삭제
    • 완성된 색인 삭제
    • 색인 닫기
      • 실제 삭제는 아닌 것 같고
      • 읽기 쓰기 작업 불허, 메모리 Load X
      • 삭제한 것과 다름이 없지만 디스크에는 남아있어 닫은 색인을 열기만 하면 복구가 된다는 장점