본문 바로가기

소프트웨어-이야기/데이터 저장소 + 시각화

(ElasticSearch) 엘라스틱서치에 데이터 싱크하기 ( 1 ) - The Problems of Too-Frequent Updates and Non-Batch Updates

이 글은 [elastic] Keeping Elasticsearch in Sync 문서를 정리한 글 입니다 ㅎㅅㅎ


ElasticSearch은 검색엔진 목적으로 많이 사용된다. 그래서 원천 데이터들은 RDB / NoSQL DB에 저장하고, 제2의 데이터 저장소로 ElasticSearch를 사용하는 경우가 많다. 그래서 원천 데이터를 ElasticSearch으로 옮기는 작업이 필요하다. 

이 글에서는 DB와 엘라스틱서치를 효율적으로 싱크시키는 방법에 대해서 정리하고자 한다. 


데이터를 복제뜨는 방법은 크게 2가지가 있다.


A. 실시간으로 데이터 싱크하기 ( sync )

B. 배치로 데이터 싱크하기 ( async )


A. 실시간으로 데이터 싱크하기 

문제 1 - 엘라스틱서치 트래픽 증가

건바이건으로 엘라스틱서치 데이터를 갱신하는 방법은 엘라스틱서치에서 너무 많은 HTTP Request를 처리하게 만든다. 

이렇게 되면 엘라스틱서치의 리소스를 효율적으로 쓰지 못하게 되는 이슈가 발생한다. ( 엘라스틱서치 서버가 데이터를 최적화하는 데에 사용할 리소스를 Request 처리에 사용하게 된다. )

그러다보면 엘라스틱서치도 느려지고, 엘라스틱서치를 사용하는 애플리케이션도 느려지게 된다. 



예를 들면, 페이지 조회수, 라이크수의 증분을 엘라스틱서치에 실시간으로 반영하는 케이스가 있다. 

이 경우 문제가 될 가능성이 높다. 

이 때, "페이지 조회 트래픽 / 라이크 트래픽 증분 ==  엘라스틱서치 트래픽 증분"이 된다 

게다가 트래픽이 많아서, 엘라스틱서치에서 Request를 처리하지 못하게되면, 원천 데이터와 엘라스틱서치 간의 데이터 정합성도 깨질 수 있다. 


문제 2 - 루씬 쓰기 퍼포먼스 이슈 

루씬은 읽기 퍼포먼스가 높은 대신, 쓰기 비용이 높은 편이다. 

루씬 INDEX는 여러 세그먼트로 구성되는데, 이 세그먼트에 있는 문서들은 imuutable하다. 즉, 세그먼트 안에 있는 문서들은 변경할 수 없다. 

그래서 문서를 업데이트한다는건, 아래의 3가지 처리가 진행된단걸 의미한다. 

-> 세그먼트에 있는 기존 문서가 지워졌다고 마킹 처리를 한다.
-> 새 문서를 만들어서, 버퍼링 처리해둔다. ( 이 새로운 문서는 새 세그먼트가 만들어질 때 사용된다 )
-> 문서를 re-analyze한다. 

이런 작업이 리소스를 잡아먹는다. 


예를 들면, posts 테이블이 있는 블로그 애플리케이션을 생각해보자. 

posts 테이블의 pageview 속성이 높을 수록 document score가 높아지고, 검색엔진에 더 많이 노출되어야한다고 생각해보자! 

- 1개의 페이지에 1000번의 노출이 발생하면, 
- RDB에 1000개의 업데이트 요청이 발생하고, 
- 다시 또 Elastic Search 1000번의 업데이트 요청이 발생하게 된다. 

RDB에서 COUNT를 1씩 증가시키는건, 크게 문제가 되지 않을 수 있다. 
그런데 엘라스틱 서치에서 카운트를 1씩 증가시킨다는건, 문서를 수정한단 의미이고, 문서를 변경한다는건 블로그 텍스트들을 재인덱싱(re-analyze)를 해야한단걸 의미한다. 

이 경우, 서버 리소스를 엄청~~많이 잡아먹게 되어서, 서비스에 심각한 문제를 발생시킬 수 있다. 



B. 배치로 데이터 싱크하기

배치로 엘라스틱서치에 데이터를 복제하는 방식을 사용하면, Document의 반복 업데이트를 줄일 수 있다.


Bulk API 

Bulk API는 한 번의 API 호출로 여러 문서를 업데이트할 수 있게 해준다.

그래서 배치로 원천 데이터들을 ElasticSearch으로 복제뜰때, Bulk API는 매우! 중요한 역할을 한다. 


왜냐하면 HTTP 요청수를 줄여주기 때문이다. 


100개의 문서를 수정할 때, 수정요청 Request를 100번 호출해야한다. 

그런데 Bulk API를 사용하면, 1번만 호출하면 된다. 


Trade Off

배치 전략을 사용하면, 원천데이터와 엘라스틱서치에 검색 싱크가 되는 데에 일정 기간 텀이 생기게 된다.

일반적으로 엘라스틱서치를 효과적으로 사용하려면, 데이터 싱크에 발생하는 지연을 감수해야한다. 


보통 엘라스틱 서치-원천 데이터가 완벽하게 싱크되어야하는 경우는 거의 없다. 

Product Owner나 비즈니스 담당자들이 완벽한 싱크를 필요로 하는 경우가 있을 수 있지만, 완벽한 실시간 싱크는 거의 불가능하다.


그래서 대부분의 실제 애플리케이션은 몇초 / 몇분 / 몇시간 / 몇일 정도의 데이터 싱크 텀을 허용하고는 한다. 


데이터 싱크에 지연없이, 실시간으로 처리하는게 가능하긴 하다. 

그런데 위에서 언급한 것처럼 데이터 유실 가능성, 서버 리소스 증가 등의 비용이 든다.



배치로 데이터를 싱크맞추는 방법은 (ElasticSearch) 엘라스틱서치에 데이터 싱크하기 ( 2 ) 에서 정리할 예정이다 ㅎㅅㅎ 


ElasticSearch 검색엔진 사용 사례 

버즈니, 공개SW 기반 모바일 홈쇼핑 포털 서비스 


참고 문서 

[elastic] Keeping Elasticsearch in Sync

[elastic] Bulk API 

[elastic] 루씬 검색엔진 이해하기

[slideshare] 검색엔진이 데이터를 다루는 법