Elastic Search

Ch10. 대용량 처리를 위한 시스템 최적화 - 엘라스틱서치와 가상 메모리

webmaster 2025. 10. 10. 12:07
728x90

가상 메모리

가상메모리
가상 메모리 한계 보기

  • 대부분의 현대 운영체제들은 가상 메모리 관리 기법을 사용하며, 애플리케이션에서 물리적인 메모리보다 많은 양의 메모리를 사용할 수 있도록 운영체제가 제공하는 대표적인 메모리 관리 기술이다.
  • 애플리케이션이 실행될 때, 메모리 번지를 직접 할당하는 것이 아닌, 가상의 메모리 번지를 생성해서 제공함으로써 애플리케이션 별로 전용 메모리 공간을 사용할 수 있다.
    • 이를 활용하면 애플리케이션이 운영체제에서 인식하고 있는 물리 메모리 크기보다 더 큰 메모리를 할당받아 사용할 수 있다.
  • 운영체제는 애플리케이션들이 CPU나 메모리 같은 시스템 리소스를 사용할 때 제한을 주고 있다.
    • 리눅스의 경우 ulimit 명령어로 애플리케이션별로 제한된 리소스의 한계를 볼 수 있다.

JVM을 위한 가상 메모리

  • Java 애플리케이션 같은 경우 실행 시, -Xms(처음 시작 힙 크기)/-Xmx(최대 힙 크기)를 설정할 수 있다.
    • ps 명령어를 통해 각 Application의 정보를 볼 수 있다.(program ID는 jps(자바 애플리케이션 목록) 명령어로 확인)
  • 운영체제에서는 효율적인 메모리 관리를 위해 메모리와 디스크 간에 데이터를 교환하는 스와핑이라는 작업을 꾸준히 수행하며, 여러 애플리케이션과 물리 메모리를 나눠 쓴다.
    • 운영체제는 가상 메모리의 데이터를 나눠 반드시 필요한 부분은 물리 메모리에 로드하고 나머지 데이터는 디스크에 임시 저장한다.
    • 프로그램이 동작하면서 메모리상 필요한 부분들은 지속적으로 변경되고, 메모리와 디스크 간 스와핑이 반복적으로 일어난다.
    • 메모리를 많이 사용할수록 스와핑 작업은 많이 일어나고 성능에 영향을 미친다.
  • 엘라스틱서치 또한 자바 기반 애플리케이션이며, 실행 시 운영체제에서 설정된 가상메모리 관련 설정을 그대로 상속 받는다.

엘라스틱서치를 위한 vm.max_map_count 설정

JAVA NIO 기술

sysctl -w vm.max_map_count = 262144
  • 루씬은 내부적으로 자바에서 제공하는 NIO 기술을 활용하며, 이를 통해 운영체제 커널에서 제공하는 mmap 시스템 콜을 직접 호출할 수 있으며, VM을 거치지 않고도 직접 커널 모드로 진입할 수 있어, 높은 성능을 낸다.
    • 엘라스틱서치는 루씬을 실행시키면서 mmap과 niofs 방식의 디렉터리를 적절히 혼용해 사용한다.
  • 커널 레벨의 파일 시스템 캐시를 사용할 수 있는 장점이 있다.
    • 운영체제에서는 파일 시스템을 캐시 하는데 커널 레벨의 메모리를 사용하는데, 루씬에서 생성한 세그먼트도 파일이기 때문에 파일 시스템 캐시를 활용할 수 있다.
    • 자바 힙 메모리에 의존하지 않고 커널 레벨에서 간접적으로 물리 메모리를 사용할 수 있게 된다.(운영 체제에 50% 메모리를 양보하는 이유)
  • 엘라스틱서치에서 루씬이 원활하게 동작하기 위해서는 가상 메모리 설정 중 mmap 크기 항목을 조정해야 하며(기본 65,530) 너무 작을 경우 운영 중 메모리 부족 문제가 발생할 수 있다.
    • 엘라스틱서치는 vm.max_map_count 설정을 초기 로딩 과정에서 검사해 수치가 262,114 이하면 오류 메시지를 출력. 인스턴스를 종료한다.
    • 따라서 엘라스틱서치를 실행하는 운영체제는 최소 vm.max_map_count 수치를 262,114 이상으로 설정해야 한다.
    • 리눅스에서 sysctl 명령어로 설정할 수 있으나, 운영체제 재부팅 시, 초기화되기 때문에 /etc/sysctl.conf 파일에서 설정하는 것을 추천한다.
참고
mmap() - memory mapping
파일 처리 성능 개선 기법(메모리에 파일을 매핑하기)
프로세스에서 파일을 읽을 때, OS의 시스템 콜을 시작으로 저장매체에 접근하여 파일을 읽기까지의 과정이 복잡하며 오래 걸린다. 더불어, 내부적으로 OS가 처리해야 하는 과정(시스템콜, 인터럽트, 스케줄링)이 많기 때문에 CPU의 성능이 떨어지기 마련이다. 이처럼 파일에 접근하는 과정의 효율성을 높이기 위해 사용하는 함수가 mmap()이다.     

mmap()의 동작방식
mmap()은 메모리의 특정 공간에 파일을 매핑한다. 프로세스는 해당 파일을 읽기 위해서 저장매체에 접근하는 것이 아닌, 메모리의 데이터에 접근하는 방식이다. 그러므로 시스템 콜, 스케줄링, 인터럽트 등 OS의 개입과 저장매체로의 접근이 필요 없다. 즉, 성능이 개선된다. 

출처: https://devraphy.tistory.com/428

niofs
NIOFS 타입은 Java NIO를 이용해 Lucene의 NIOFSDirectory 위에서 동작하며, 여러 스레드가 동시에 같은 파일을 읽을 수 있게 해 검색 처리 성능을 높인다. 다만, Sun Java의 Windows 구현체에서 알려진 버그로 인해 Windows 환경에서는 권장되지 않으며, 일부 힙 메모리 최적화 기능이 비활성화된다.
728x90