전 회사에서 Data Lake + Data WareHouse의 느낌으로 ElasticSearch를 사용했었다. 그때의 기억을 되살려 관련 정보를 정리해보고자 한다.
고가용성 : 시스템이나 네트워크가 높은 수준의 운영 시간(uptime)과 최소한의 다운타임을 보장하는 능력. 즉, 시스템이나 서비스가 계획되지 않은 중단 없이 지속적으로 작동할 수 있는 능력을 의미
discovery.zen.minimum_master_nodes
설정으로 네트워크 분할 발생 시 하나의 서브 클러스터만 마스터 노드를 가질 수 있게 하여 Split Brain
문제 해결 가능Split Brain 문제 : 클러스터에 특정 에러가 발생해 네트워크 분할이 발생했을 때 나타나는 문제, 분리된 각 서브 클러스터는 독립적으로 마스터 노드를 선출하게 되고 각 서브클러스터마다 데이터를 변경하게되면 이후 에러를 해결하고 다시 합치게 될 때 데이터 일관성에 문제가 생김.
ElasticSearch | RDBMS |
---|---|
Index | Database |
Shard | Partitioning |
Type | Table |
Document | Record |
Field | Column |
Mapping | Schema |
DSL | SQL |
Index
Shard
Segment
라는 물리적 파일에 저장됨.Type은 ES 7.0 이전에 Index 내에서 문서를 구분하는데 사용되었지만, 7.0 이후 부터는 없어짐
DSL은 ES에서 검색, 집계 등을 위해 사용되는 JSON 기반의 쿼리 언어
역인덱스는 텍스트 기반 검색을 빠르게 수행할 수 있게 해주는 데이터 구조.
> B-Tree 검색 과정 : 검색을 시작하면 루트 노드에서 시작해 Key 값을 비교하면서 검색하려는 키가 위치할 수 있는 자식 노드로 내려간다. 이 과정일 재귀적 반복하여 검색하려는 Key를 포함하고 있는 노드를 찾는다. 이 것은 트리가 정렬 된 상태로 유지되기 때문에 가능함.
Key : List[Value]
형태가됨.Inverted Index 생성과정에서 텍스트 데이터를 토큰화 하는 과정도 포함되는데, 이 토큰화를 담당하는 도구를 Analyzer
라고 부른다.
analyzer는 클러스터나 특정 인덱스에 의해 정의되고 관련된 모든 노드에서는 사용할 수 있다.
Character Filters : 텍스트를 분석하기 전에 사전 처리 단계에서 사용. HTML 태그 제거, 불필요한 문자 제거, 특정 문자를 다른 문자로 대체하는 작업을 수행. ex) "<"와 ">" 같은 HTML 태그를 제거하거나, "$" 문자를 "dollar"로 변경
Tokenizer : 정규화된 텍스트는 토크나이저에 의해 개별 토큰으로 분리되는데, ES에서는 다양한 토크나이저를 제공함. 가장 기본적인 토크나이저는 공백을 기준으로 분리하는 standard
, 특수한 문자를 구분자로 사용하는 pattern
Token Filtering : 토큰화 과정 이후 'a', 'the' 와 같은 불용어(Stop Word), 동의어(Synonym) 등을 제거하는 역할
전 회사 프로젝트에서 ElasticSearch를 운영할 때, Heap Memory가 부족하다거나 log가 너무 많이 쌓여서 문제가 된 적이 있다.
원인이 무엇인지 파악하다가 ElasticSearch에서는 document를 update 할 때, 해당 데이터가 실제로 저장된 segment에서 update 되는 것이 아니라 업데이트된 document는 새로운 segment에 저장되고 기존 segment는 삭제되는 방식으로 처리된다는 것을 알게 됐다.
{
"name": "맛있는 식당",
"location": "서울",
"cuisine": "한식",
"menus": [
{
"name": "김치찌개",
"price": 8000,
"ingredients": ["김치", "돼지고기", "두부"]
},
{
"name": "된장찌개",
"price": 7500,
"ingredients": ["된장", "콩나물", "호박"]
}
]
}
예를들어, 위의 예시에서 "김치찌개" 를 "부대찌개"로 변경한다고 가정해보면 Index에서 해당 Document는 삭제되고 새로 생성되는 것이다.
위와 같이 중첩 구조를 사용할 때, nested
타입을 지정할 수 있는데 해당 타입을 지정하면 중첩된 객체는 개별 문서로 취급되지만 상위 Document의 segment에 데이터가 저장되기 때문에
상위, 하위 document 중 하나만 변경하더라도 모두 새로운 segment에 저장된다.
회사에서 운영 중인 ETL 파이프라인은 DB 로그를 읽어와 ElasticSearch에 저장하고, 이후 해당 데이터를 서비스 DB로 이전하는 과정에서 ElasticSearch에 대한 업데이트 작업을 수행한다. 이러한 절차를 거친다면, 로그를 매번 읽어올 때마다 상당한 양의 쓰기(Write) 작업이 발생했을 것으로 추정된다.
어떻게 이 문제를 해결할 수 있을까 검색하다보니 비슷한 상황을 해결한 글을 발견했다! https://techblog.woowahan.com/7425/