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
장점
단점
Data Sync Pipeline 구축, 유지 보수
ES는 많은 메모리 리소스를 요구한다. Out of memory 에러가 발생하기 쉽다.
ref
Using Elasticsearch to Offload Real-Time Analytics from MongoDB
https://rockset.com/blog/using-elasticsearch-to-offload-real-time-analytics-from-mongodb/
MongoDB와 Elasticsearch 연동에 Monstache를 사용한다. Monstache를 사용하려면 우선 MongoDB에 레플리카 셋을 구성해야 한다.
레플리카 셋은 데이터베이스의 고가용성 환경 구성을 위해 사용된다. Monstashe는 MongoDB의 변경 사항을 Oplog와 Change stream를 통해 관찰한다. Oplog와 Change stream이 생성되려면 MongoDB에 레플리카 셋을 필수적으로 구성해야 한다.
레플리카 셋 개념
Primary: 클라이언트에서 DB로 읽기 및 쓰기 작업을 한다. 레플리카 셋에서 단 하나만 존재 할 수 있다.
Secondary: Primary 로부터 데이터를 동기화 한다. 투표권을 가지고 있다. 클라이언트의 읽기 작업을 분담할 수 있다.
Arbiter: 데이터를 동기화하지 않으며 레플리카 셋의 복구를 돕는 역할을 한다.
레플리카 셋 구성원들 사이에는 주기적으로 10초에 한번씩 ping을 보내 서로의 노드를 확인한다. (Heartbeat)
장애가 발견되면 secondary 노드 중 하나를 primary로 올리는데, 이때 투표권을 가진 노드들이 pimary가 될 노드를 결정한다.
레플리카 셋은 최소 3대 이산 구성원, 홀수로 노드의 수를 늘리는 것을 권장한다. (선거에서 다수결 투표를 위함)
레플리카 셋의 선거
레플리카 셋 구성하기
mongod.conf
파일에서 replSetName와 Bind IP를 설정한다.
replication:
replSetName: "rs0"
net:
bindIp: 0.0.0.0
각 노드마다 사용할 dbpath 폴더를 생성한다.
레플리카 셋 구성원 모두 따로 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
노드 하나에 접속한다. (마스터 포트 연결)
mongo --port 27017
rsconf 생성
> rsconf = {_id: "rs0", memebers: [{_id: 0, host: "localhost:27017"}]}
rs.initiate(rsconf)
화면에 “ok”: 1가 뜨고, rs0: PRIMARY>
로 바뀌면 된다.
Secondary 포트 추가
rs0: PRIMARY> rs.add(”localhost:27020”)
rs0: PRIMARY> rs.add(”localhost:27021”)
Primary 노드에서 rs.status()
를 입력해 상태를 확인할 수 있다.
Secondary에서는 Mongo Shell을 사용하려면 rs.secondaryOk()
를 입력해야 한다.
Monstache는 MongoDB와 Elasticsearch를 실시간으로 동기화하는 sync daemon이다.
Monstache Docs: https://rwynn.github.io/monstache-site/
Monstache 다운로드
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-url | MongoDB connection string |
---|---|
elasticsearch-urls | Elasticsearch url |
direct-read-namespaces | monstache 실행 시 작성된 컬렉션 전체를 복사한다. 복사할 컬렉션은 “DB이름.컬렉션이름” 형식으로 작성해야 한다. Direct-read로 작성되지 않은 컬렉션은 monstache 실행 후 변경된 사항이 동기화 된다. |
elasticsearch-max-conns | Size 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-user | ES username for basic auth. |
elasticsearch-password | ES password for basic auth. |
dropped-collections | MongoDB에서 컬렉션을 드롭했을 때 ES에 적용할 것인지 설정한다. 디폴트 값은 false이므로 기본적으로 ES에 드롭을 적용하지 않는다. |
dropped-databases | MongoDB에서 데이터베이스를 드롭했을 때 ES에 적용할 것인지 설정한다. 디폴트 값은 false이므로 기본적으로 ES에 드롭을 적용하지 않는다. |
gzip | 디폴트 값은 false. true로 설정하면 monstache가 ES로 보내는 요청을 압축한다. |
logs | info warn error trace stats 로그를 남길 경로를 작성할 수 있다. |
mapping | MongoDB에서 ES로 인덱싱할 때 매핑을 정의할 수 있다. |
https://rwynn.github.io/monstache-site/advanced/#index-mapping |
Monstache 실행
monstache.exe -f path/to/config.toml
MongoDB(레플리카셋 포함)와 Elasticsearch 모두 실행된 상태에서 Monstache를 실행한다.
확인
http://localhost:9200/_cat/indices?v
로 Elasticsearch에 복제된 인덱스를 확인하거나,
ES와 연동된 Kibana에서 확인할 수 있다.
MongoDB에 새로운 데이터를 추가하고, ES에서 검색하여 확인한다.