티스토리 뷰
들어가는 말
elasticsearch(이하 es)에서 데이터가 어떻게 저장되는지 궁금해서 이글 저글 짜깁기해보면서 정리
필요한 배경
es는 lucene(이하 루씬) 기반이다.
es는 인덱스를 기반으로 데이터를 저장하고, 각 인덱스는 샤드로 구성되어 있으며, 각 샤드는 루씬의 인덱스이다. (es의 샤드와 루씬의 인덱스는 1:1 관계)
샤드는 es의 데이터 노드들에서 관리하고, 데이터에 대한 crud나 그 외 연산(검색, 집계 등)을 수행한다. (즉 루씬에서 수행한다는 소리다.)
샤드는 레플리카로 관리할 수 있다.
es에서 관리하는 데이터는 세그먼트로 관리된다.
세그먼트 inverted index이다. (term을 추출하여, term 이 어느 doc에 있는지 관리)
세그먼트는 파일로 쓰이기 전까지 translog 로도 관리된다.(DR용도)
세그먼트는 불변이다. (정말 불변 맞나? delete는 그렇다고 쳐도 update 가 되긴 하던데)
샤드는 여러 개의 세그먼트로 구성될 수 있다.(하나로도 구성이 가능할 것 같다.)
es랑 루씬이랑 용어가 다른 부분이 있다. (flush라는 단어가 겹쳐버려서 헷갈릴 여지가 많다.)
es | 루씬 |
refresh | flush |
flush | commit |
optimize/forcemerge | merge |
배경이 괜히 길다...
간단 요약
es에 인입된 데이터들은 바로 사용(검색)이 불가능하고, 영속적으로 디스크에 저장되지도 않는다.
몇 단계를 거쳐서 이뤄진다.
es의 refresh의, 루씬의 flush
검색이 가능해진다.
세그먼트 파일이 생성된다.
write()를 호출한다.
es의 flush, 루씬의 commit
디스크에 영속적으로 저장이 된다.
fsync()를 호출한다. (이전까지는 해당 파일은 커널에서만 관리되고 있었지, 커널에서 시스템 캐시에 파일만 생성되었을 뿐, 실제 디스크에 저장된 상태가 아니었다.) (와... 결국 이거였다.)
https://lwn.net/Articles/457667/
es의 optimize, 루씬의 merge
여러 개 세그먼트를 합친다.
이 시점에서 삭제 마킹해둔 데이터를 삭제한다.
es의 refresh의, 루씬의 flush
https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-refresh.html
es의 메모리 버퍼에서 담고 있던 파일을 검색 가능하게 만들어준다.
세그먼트 파일이 생성된다.
내부적으로는 write system call을 호출한다.
주기적으로 호출된다. (강제로도 부를 수 있긴 한데)
단, 이 시점까지는 디스크에 영속적으로 저장된 게 아니다.
파일이 생성되었는데 디스크에 영속적으로 저장된 게 아니라고?
$ man 2 write
잘 읽어보면 힌트가 매우 많다.
버퍼의 내용을 fd에 쓴다고만 설명하고 있다. Note 에는 대놓고 디스크에 커밋된 게 아니라고 말하고 있다.
A successful return from write() does not make any guarantee that data has been committed to disk. On some
filesystems, including NFS, it does not even guarantee that space has successfully been reserved for the data.
In this case, some errors might be delayed until a future write(), fsync(2), or even close(2). The only way to
be sure is to call fsync(2) after you are done writing all your data.
es의 flush, 루씬의 commit
https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-flush.html
이 과정에서 세그먼트 파일이 디스크에 영속적으로 저장이 된다.
비싼 연산이다.
디스크에 영속적으로 저장하니까 유실 위험이 없어진다.
내부적으로 fsync()를 호출한다.
번외로 그 이전까지 관리하고 있던 transaction log(이하 translog)을 삭제하고 새로 만든다.
(es의 flush api의 설명을 보면 translog 처리는 번외로 말할 수준이 아니다.)
세그먼트 이야기하다가 뜬금없이 translog 인가.. 싶지만,
es에서는 문서가 인입될 때 refresh 과정과는 별개로 translog 파일로 변경사항을 기록하고 있고, 세그먼트가 flush 되기 전에 유실될 수 있으므로, coomit 되지 않은 변경사항들을 translog를 통해 복구한다.
https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-translog.html
es의 optimize/forcemerge, 루씬의 merge
예에에에전 optimize api 가 forcemerge로 바뀐 것 같은데...
맞다.
https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-forcemerge.html
여러 개 세그먼트를 합친다.
이 시점에서 삭제할 거라고 마킹해둔 데이터를 삭제한다.
왜 여러 개의 세그먼트를 합치냐면...
여러 개 파일을 읽어야 하기 때문이 아닐까? (맞는 것 같다.)
그 외에 메모리가 줄어드는 효과도 있다고 한다. (이건 비용 관련되어 있다 보니 굉장히 재미있는 주제인데...)
https://deviscreen.tistory.com/67
세그먼트가 inverted index 구조이니까 중복된 term들이 합쳐지게 되는 효과인 것 같다.
물론 쓰기가 진행 중인 샤드(즉 인덱스)에 대해 수행하는 건 위험해 보인다.
forcemerge를 호출하는 경우는 freeze 전에 호출한다고 하는데... 이 주제도 굉장히 재미있어 보이는데...
어차피 일단위로 인덱스 관리하고 한두 달 전 데이터가 그렇게 빠르게 검색될 필요는 없으니... ILM 쓰고 싶다. :(
https://www.elastic.co/kr/blog/creating-frozen-indices-with-the-elasticsearch-freeze-index-api
나가는 말
역시나 좀 더 파보면 그만큼 재미있다.
es는 ssd에서 굴려야 한다.
es를 db 처럼 쓸 수 있긴 한데... 제발 좀 :(
write(), fsync()를 조금 더 파봐야 하나... (이 주제는 db 쪽 아티클들에 많은 것 같다. os cache와 fsync)
세그먼트가 inverted index라고 알고는 있는데 구체적으로 어떻게 저장되는 거지? 이것도 까 볼까...
그럼 데이터노드에 heap 에는 뭐가 올라가 있는 거지? 절반만 쓰고 나머지는 루씬에 양보하라고 하던데...
성능 튜닝 쪽 아티클들 읽다 보면 레플리카 1로 해서 빨리 저장하는 것도 방법이라고 하는데, 그럼 샤드의 레플리카 복제 시점은 언제지? 어떤 데이터를 복제하는 거지?
세그먼트 inverted index이다...가 납득이 잘 안되는데 그럼 문서 원문은 어디 보관되는 거지?
출처
https://coding-start.tistory.com/178
https://coding-start.tistory.com/176
https://doubly12f.tistory.com/96
https://www.programmersought.com/article/87524159406/
https://qbox.io/blog/refresh-flush-operations-elasticsearch-guide/
https://qbox.io/blog/maximize-guide-elasticsearch-indexing-performance-part-2/
https://lwn.net/Articles/457667/
https://scslab-intern.gitbooks.io/linux-kernel-hacking/content/chapter16.html
'개발관련 > 오픈소스(들?)' 카테고리의 다른 글
Opensearch (aws elasticsearch) (0) | 2021.08.08 |
---|---|
kafka 카프카 관리하기 (0) | 2021.07.07 |
elasticsearch percolate search POC (0) | 2021.07.07 |
로컬 환경에 kakfa 설치 및 구성 (0) | 2021.06.23 |
kafka 2.8.0 (0) | 2021.05.16 |
- Total
- Today
- Yesterday
- 기술사이트
- 말의품격
- 기술센싱
- opensearch
- PatternSyntaxException
- 에픽테토스
- elasticsearch
- 개발자
- Generic
- jhipster
- meta character
- 클린 아키텍처
- 만들면서 배우는 클린 아키텍처
- Java
- 사기꾼증후군
- flush
- 기술블로그
- completablefuture
- kafka 2.8.0
- pecs
- Kafka
- fsync
- Spring
- COMMIT
- Async
- Dangling
- WebSocket
- percolate
- 전설로떠나는월가의영웅
- AWS
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |