Blog

[Spring][258] Elasticsearch 검색 성능 개선 05 MySQL→Logstash-Elasticsearch 연결 설정, Heap Space 부족 트러블 슈팅

Category
Author
Tags
PinOnMain
1 more property
MySQL - Logstash - Elasticsearch의 연결을 하는 이유?
간단히 mysql의 데이터를 사용해서 elasticsearch에서 검색을 하기위해서는 elasticsearch DB에 데이터를 담아야합니다. 이를위한 도구로서 Logstash를 사용하게 됩니다.
Logstash을 사용하여 MySQL과 Elasticsearch 간의 데이터 전송을 쉽게 설정할 수 있습니다. Logstash은 다양한 데이터 소스에서 데이터를 수집하고 처리하여 다른 저장소로 전송하는 역할을 합니다.
해당 과정은 Elasticsearch, Logstash, Kibana인 ELK 스택을 설치한 이후로 진행되는 과정입니다. 아래 링크를 통해 설치와 실행 상태를 확인후 진행해야 합니다.
설치와 관련된 링크 참고
우선 Logstash를 통해 Elasticsearch에 데이터가 전달되어야 한다.
Logstash를 통한 Elasticsearch 데이터 전달 설정 절차
1.
Logstash 설치: 먼저 Logstash을 설치합니다.
2.
Logstash 설정 파일 작성: Logstash은 설정 파일을 통해 입력(Input), 필터(Filter), 출력(Output)을 정의합니다. MySQL과 Elasticsearch 간의 연결 정보를 설정합니다.
3.
Logstash 실행: 작성한 Logstash 설정 파일을 사용하여 Logstash을 실행합니다.
Logstash 설정 파일 위치 확인
Logstash의 설정 파일은 설치된 디렉토리에 위치한다. 로컬에 설치했으므로,
/usr/local/Cellar/logstash-full/7.17.4/libexec/config 이 경로에 conf파일을 생성해준다.
Logstash 설정 파일 작성
여기서 your_database, your_username, your_password, your_table, your_index 등을 실제 환경에 맞게 수정해야 합니다.
# mysql_to_elasticsearch.conf input { jdbc { jdbc_connection_string => "jdbc:mysql://localhost:3306/your_database" jdbc_user => "your_username" jdbc_password => "your_password" jdbc_driver_library => "/path/to/mysql-connector-java.jar" jdbc_driver_class => "com.mysql.cj.jdbc.Driver" schedule => "* * * * *" statement => "SELECT * FROM your_table" } } output { elasticsearch { hosts => ["localhost:9200"] index => "your_index" document_id => "%{id}" } }
Java
복사
테스트를 위해 제가 실제로 작성한 conf 파일의 내용은 다음과 같습니다.
# sample.conf input { jdbc { jdbc_connection_string => "jdbc:mysql://localhost:3306/team258" jdbc_user => "inyongkim" jdbc_password => "1234" jdbc_driver_library => "/Users/inyongkim/.gradle/caches/modules-2/files-2.1/mysql/mysql-connector-java/8.0.25/f8b9123acd13058c941aff25f308c9ed8000bb73/mysql-connector-java-8.0.25.jar" jdbc_driver_class => "com.mysql.cj.jdbc.Driver" schedule => "* * * * *" statement => "SELECT * FROM book" } } output { elasticsearch { hosts => ["localhost:9200"] index => "book" document_id => "%{book_id}" } }
Java
복사
Logstash 실행
위 설정 파일을 저장하고 실행 커맨드를 다음처럼 실행합니다.
이 명령어를 실행하면 Logstash가 해당 설정 파일을 사용하여 MySQL에서 데이터를 가져와 Elasticsearch로 전송하게 됩니다. 실행 중에 에러가 없다면 데이터가 Elasticsearch에 잘 전송되고 색인됩니다.
/usr/local/bin/logstash -f /usr/local/etc/logstash/sample.conf
Shell
복사
오류 발생 - OutOfMemoryError(Java heap space)
로그스태시가 정상적으로 시작되었습니다. 하지만 일정 시간 이후 갑자기 Java heap space에 대한 OutOfMemoryError가 발생했습니다.
로그스태시가 Java heap space 오류로 실행이 정상적으로 진행되지 않습니다. 이 오류는 Java 가상 머신의 힙 메모리가 부족해서 발생하는데, Logstash의 기본 힙 크기는 실행 환경에 따라 부족할 수 있다고 합니다.
우선 JVM의 메모리를 늘리는 방법으로 해결해보고자 했습니다. 실행 명령어에 이와 같이 -J-Xmx 을 붙여서 실행해봅니다.
/usr/local/bin/logstash -f /usr/local/etc/logstash/sample.conf -J-Xmx=2g
Shell
복사
하지만 위 명령어를 인식하지 못합니다.
/usr/local/bin/logstash -f /usr/local/etc/logstash/sample.conf --java-execution-heap-size=2g
Shell
복사
위 명령어 또한 인식이 안됩니다. conf파일 자체에서의 수정이 필요합니다.
sample.conf 파일에 paging을 추가하여 분산하여 로딩
데이터를 작은 묶음으로 가져와서 메모리 부하를 줄이는 방법을 선택하게 되었습니다. 710만건을 한번에 메모리에 올리다보니 메모리 부족현상이 있었지만, 50000건씩 로드, 이동, 소멸하는것을 반복하도록 지정했습니다.
# sample.conf input { jdbc { jdbc_connection_string => "jdbc:mysql://localhost:3306/team258" jdbc_user => "inyongkim" jdbc_password => "1234" jdbc_driver_library => "/Users/inyongkim/.gradle/caches/modules-2/files-2.1/mysql/mysql-connector-java/8.0.25/f8b9123acd13058c941aff25f308c9ed8000bb73/mysql-connector-java-8.0.25.jar" jdbc_driver_class => "com.mysql.cj.jdbc.Driver" jdbc_paging_enabled => true jdbc_page_size => 50000 # 페이징 크기를 조정하세요. schedule => "* * * * *" statement => "SELECT * FROM book" } } output { elasticsearch { hosts => ["localhost:9200"] index => "book" document_id => "%{book_id}" } }
Shell
복사
이제 정상적으로 데이터가 색인되고 있는 모습입니다.
계속해서 쿼리를 조회하고 반복한다 이 상태가 정상인것으로 보여진다.
이게 schedule => "* * * * *" # Query주기 설정 에 따라서
매 분마다 SELECT * FROM book_category 쿼리를 실행하여 데이터를 가져오고 Elasticsearch로 전송하고 있어. Logstash가 계속해서 데이터를 가져오고 Elasticsearch에 전송하는 동작을 수행하고 있는것.