MongoDB - Elasticsearch 동기화 (using Monstache)

quokka·2022년 6월 12일
0

.

목록 보기
4/5

MongoDB와 Elasticsearch를 동기화하는 이유

Elasticsearch도 데이터베이스의 역할을 할 수 있으므로 로그 데이터를 저장하는 DB로 사용할 수 있다. 하지만 ES를 MongoDB와 연동하여, 검색과 분석에 필요한 데이터만 필터링해 ES에 저장하고, ES에서는 오래된 로그 데이터는 삭제하면서 사용하면 더 높은 성능으로 사용할 수 있다. 또한 ES는 아래와 같은 이유로 메인 데이터베이스로 사용하는 것을 권장하지 않는다.

  • ES는 데이터베이스 트랜잭션, ACID 속성을 보장하지 않는다.

    https://esbook.kimjmin.net/04-data/4.3-_bulk
    Elasticsearch 에는 커밋이나 롤백 등의 트랜잭션 개념이 없습니다. _bulk 작업 중 연결이 끊어지거나 시스템이 다운되는 등의 이유로 동작이 중단 된 경우에는 어느 동작까지 실행되었는지 확인이 불가능합니다. 보통 이런 경우 전체 인덱스를 삭제하고 처음부터 다시 하는 것이 안전합니다.

  • 많은 양의 데이터가 들어오면 인덱싱 작업으로 인해 빠른 검색이 어렵다.

    ES를 사용하는 이유이자 강점이 거의 실시간 검색이 가능하다는 것인데, ES는 인덱싱 비용이 높기 때문에 데이터 입력이 많으면 빠른 검색 기능을 제대로 활용할 수 없다.

    그래서 MongoDB는 메인 데이터 저장소로 빠른 데이터 가져오기(data ingestion)에 사용하고, 검색과 분석에 필요한 필드만 커스텀 매핑으로 ES에 동기화한다.

  • 대부분의 기업은 ES를 메인 데이터베이스를 보조하는 search engine으로 사용한다. ES의 목적은 거의 실시간으로 검색 결과를 얻는 것이지, reliable result를 얻는 것이 아니다.

  • reference
    ES를 메인 DB로 사용하면 안되는 이유
    https://bonsai.io/blog/why-elasticsearch-should-not-be-your-primary-data-store
    https://dev.to/er_dward/elasticsearch-as-a-primary-database-15a5

    ES는 트랜잭션, 롤백을 지원하지 않는다.
    https://dbdb.io/db/elasticsearch
    https://esbook.kimjmin.net/04-data/4.3-_bulk

동기화 장단점

장점

  • MongoDB에서 분석 과정을 분리한다.
  • write 작업과 read 작업을 분리할 수 있다. (데이터 양이 많은 경우 하나에서 두 가지 모두 높은 효율을 내기 어렵고, Lucene은 read 퍼포먼스가 높은 대신, write 비용이 높다.)
  • Elasticsearch에서 제공하는 다양한 검색, 분석 기능을 사용할 수 있다.
  • Kibana 데이터 시각화

단점

동기화 하기

MongoDB와 Elasticsearch 연동에 Monstache를 사용한다. Monstache를 사용하려면 우선 MongoDB에 레플리카 셋을 구성해야 한다.

MongoDB Replica set

레플리카 셋은 데이터베이스의 고가용성 환경 구성을 위해 사용된다. Monstashe는 MongoDB의 변경 사항을 Oplog와 Change stream를 통해 관찰한다. Oplog와 Change stream이 생성되려면 MongoDB에 레플리카 셋을 필수적으로 구성해야 한다.

레플리카 셋 개념

  • Primary: 클라이언트에서 DB로 읽기 및 쓰기 작업을 한다. 레플리카 셋에서 단 하나만 존재 할 수 있다.

  • Secondary: Primary 로부터 데이터를 동기화 한다. 투표권을 가지고 있다. 클라이언트의 읽기 작업을 분담할 수 있다.

  • Arbiter: 데이터를 동기화하지 않으며 레플리카 셋의 복구를 돕는 역할을 한다.

  • 레플리카 셋 구성원들 사이에는 주기적으로 10초에 한번씩 ping을 보내 서로의 노드를 확인한다. (Heartbeat)

  • 장애가 발견되면 secondary 노드 중 하나를 primary로 올리는데, 이때 투표권을 가진 노드들이 pimary가 될 노드를 결정한다.

  • 레플리카 셋은 최소 3대 이산 구성원, 홀수로 노드의 수를 늘리는 것을 권장한다. (선거에서 다수결 투표를 위함)

  • 레플리카 셋의 선거

    • 구성원의 과반이 동의
    • 2대의 노드로 구성했을 경우 선거 자체가 열리지 않고 자동으로 primary가 스스로 secondary가 된다.
    • 우선순위가 높고, 가장 최신 정보를 가지고 있는 Secondary가 Primary 후보가 된다.
    • 레플리카 셋 구성원은 최대 50개이지만 투표권은 최대 7개
    • 투표에 의해 새로운 primary가 뽑혔는데 더 최신 데이터를 가진 secondary가 있다면 새로운 primary의 정보에 맞게 Rollback한다.

레플리카 셋 구성하기

  1. mongod.conf 파일에서 replSetName와 Bind IP를 설정한다.

    replication:
       replSetName: "rs0"
    net:
       bindIp: 0.0.0.0
  1. 각 노드마다 사용할 dbpath 폴더를 생성한다.

  2. 레플리카 셋 구성원 모두 따로 MongoDB 데몬을 구동한다. 레플리카 셋 이름은 동일하게, dbpath는 다르게 구성한다. (dbpath는 데이터를 저장할 공간에 폴더를 생성해 경로를 지정하면 된다.)

    mongod.exe --bind_ip=0.0.0.0 --dbpath=path\to\node1 --replSet "rs0" --port 27017

    mongod.exe --bind_ip=0.0.0.0 --dbpath=path\to\node2 --replSet "rs0" --port 27020

    mongod.exe --bind_ip=0.0.0.0 --dbpath=path\to\node3 --replSet "rs0" --port 27021

  1. 노드 하나에 접속한다. (마스터 포트 연결)

    mongo --port 27017

  1. rsconf 생성

    > rsconf = {_id: "rs0", memebers: [{_id: 0, host: "localhost:27017"}]}
  1. rs.initiate(rsconf)

    화면에 “ok”: 1가 뜨고, rs0: PRIMARY> 로 바뀌면 된다.

  2. Secondary 포트 추가

    rs0: PRIMARY> rs.add(”localhost:27020”)
    rs0: PRIMARY> rs.add(”localhost:27021”)
  3. Primary 노드에서 rs.status()를 입력해 상태를 확인할 수 있다.

  4. Secondary에서는 Mongo Shell을 사용하려면 rs.secondaryOk()를 입력해야 한다.

Monstache

Monstache는 MongoDB와 Elasticsearch를 실시간으로 동기화하는 sync daemon이다.

Monstache Docs: https://rwynn.github.io/monstache-site/

  1. Monstache 다운로드

    https://github.com/rwynn/monstache/releases

  2. TOML 형식 configuration 작성

    https://rwynn.github.io/monstache-site/config/

    config.toml 파일을 생성하고 configuration 옵션을 작성한다. 설정 가능한 전체 옵션은 위 링크에서 확인할 수 있다.

    옵션을 통해 동기화 주기, 실행 시 전체 복사할 컬렉션 지정, 제외할 컬렉션, 특정 확장자 제외 등 다양한 설정이 가능하다.

    # Example
    
    mongo-url = "mongodb://localhost:27020"
    
    elasticsearch-urls = ["http://localhost:9200"]
    
    direct-read-namespaces = ["dbname.collectionname", "db1.collection1"]
    
    elasticsearch-max-seconds = 5
    
    elasticsearch-max-bytes = 8000000
    
    [logs]
    info = "path/to/logs/info.log"
    warn = "path/to/logs/warn.log"
    error = "path/to/logs/error.log"
    trace = "path/to/logs/trace.log"

    주요 옵션

    mongo-urlMongoDB connection string
    elasticsearch-urlsElasticsearch url
    direct-read-namespacesmonstache 실행 시 작성된 컬렉션 전체를 복사한다. 복사할 컬렉션은 “DB이름.컬렉션이름” 형식으로 작성해야 한다. Direct-read로 작성되지 않은 컬렉션은 monstache 실행 후 변경된 사항이 동기화 된다.
    elasticsearch-max-connsSize of the Elasticsearch HTTP connection pool. 디폴트 값은 4이다.
    elasticsearch-max-seconds작성된 초에 따라 주기적으로 ES로 bulk index request를 한다. 디폴트 값을 1이지만 direct read namespaces가 감지되면 자동으로 5초까지 늘어난다.
    elasticsearch-max-bytes커넥션 버퍼가 max-bytes에 도달하면 ES로 bulk index request를 한다. max-seconds가 아직 되지 않아도 버퍼가 차면 요청한다. 디폴트 값은 8MB이다.
    change-stream-namespaces(MongoDB 3.6+) 이 옵션을 사용하면 oplog tailing은 disabled되고, 대신 change streams를 사용해서 MongoDB의 변경을 확인한다.
    elasticsearch-userES username for basic auth.
    elasticsearch-passwordES password for basic auth.
    dropped-collectionsMongoDB에서 컬렉션을 드롭했을 때 ES에 적용할 것인지 설정한다. 디폴트 값은 false이므로 기본적으로 ES에 드롭을 적용하지 않는다.
    dropped-databasesMongoDB에서 데이터베이스를 드롭했을 때 ES에 적용할 것인지 설정한다. 디폴트 값은 false이므로 기본적으로 ES에 드롭을 적용하지 않는다.
    gzip디폴트 값은 false. true로 설정하면 monstache가 ES로 보내는 요청을 압축한다.
    logsinfo warn error trace stats 로그를 남길 경로를 작성할 수 있다.
    mappingMongoDB에서 ES로 인덱싱할 때 매핑을 정의할 수 있다.
    https://rwynn.github.io/monstache-site/advanced/#index-mapping
  3. Monstache 실행

    monstache.exe -f path/to/config.toml

    MongoDB(레플리카셋 포함)와 Elasticsearch 모두 실행된 상태에서 Monstache를 실행한다.

  4. 확인

    http://localhost:9200/_cat/indices?v 로 Elasticsearch에 복제된 인덱스를 확인하거나,

    ES와 연동된 Kibana에서 확인할 수 있다.

    MongoDB에 새로운 데이터를 추가하고, ES에서 검색하여 확인한다.

0개의 댓글