ELO
행복하게 살자!
ELO
전체 방문자
오늘
어제
  • 분류 전체보기 (25)
    • 자료구조 (5)
    • 자바 (6)
      • 이펙티브자바 (3)
      • 모던 자바 인 액션 (0)
    • 스프링 (2)
      • 토비의 스프링 (0)
    • 네트워크 (1)
    • 운영체제 (1)
    • 데이터베이스 (2)
      • MongoDB (1)
      • MySQL (0)
    • 우아한테크코스 (4)
      • prolog (4)
      • 회고 (0)
    • 대규모 서비스 (0)
      • ddd (0)
      • msa (0)
    • JPA (0)
    • Infrastructure (3)
      • Docker & Kubernetes (3)

최근 글

hELLO · Designed By 정상우.
ELO

행복하게 살자!

데이터베이스/MongoDB

Real MongoDB - (1)

2023. 1. 7. 05:10

1. MongoDB


데이터베이스 트렌드

  • 기존의 데이터베이스 관리 시스템은 RDBMS가 중심, but 구글이나 페이스북과 같은 글로벌 서비스를 제공하는 회사가 늘어나면서
    방대한 양의 데이터를 충분히 빠른 속도로 처리할 수 있는 데이터베이스에 대한 필요성이 생김.
  • HBase, 카산드라 등장 -> 자바 언어로 개발되어 GC가 부담, 또한 클러스터 구축을 위한 컴포넌트가 너무 많아 관리 및 트러블 슈팅이 상대적으로 어려움.
  • MongoDB는 온라인 서비스에 필요한 블록 캐시, 보조 인덱스, 동시성 처리를 위한 스킵리스트, 하자드 포인터 등의 특성을 가지고 있음. WiredTiger 스토리지 엔진을 주로 사용 (아직 무슨말인지 잘 모르겠네요 ㅠ)

MongoDB vs RDBMS

  • MongoDB는 쿼리 결과로 커서를 반환하는데 커서를 통해 도큐먼트를 반복적으로 가져올 수 있음 -> 쿼리의 결과를 서버의 메모리에 모두 담아두지 않아도 처리할 수 있게 하기 위함 (지정된 페이지 사이즈 단위로 가져옴)
  • MongDB의 특징
    • NoSQL : SQL 인터페이스 사용 x. 외래키를 명시적으로 지원하지는 않지만 논리적으로 도큐먼트간의 관계를 만들 수 있긴 함
    • Schema Free - 테이블의 컬럼 수준에만 적용. 사용할 컬럼을 미리 정의하지 않고 언제든지 필요한 시점에 데이터를 저장할 수 있음.
    • 비 관계형 데이터베이스
    • 도큐먼트에서 id라는 이름의 필드가 자동으로 그 도큐먼트의 프라이머리 키로 선정
    • value의 json 값을 문자열로 그대로 저장하는 것이 아니라 문자열 기반의 JSON 텍스트를 BSON으로 변환해 저장

2. 스토리지 엔진


스토리지 엔진은 사용자의 데이터를 디스크와 메모리에 저장하고 읽어오는 역할을 담당 (옵티마이저, 서버등의 역할은 MySQL과 비슷해 보임)

MongoDB Storage Engine

  • MMAPv1
    • 출시부터 존재한 엔진
  • WiredTiger
    • 3.0부터 도입된 새로운 스토리지 엔진
  • In-Memory
    • WiredTiger의 변형, 데이터를 디스크에 저장하지 않고 메모리에 보관
  • RocksDB
    • 페이스북에서 LevelDB를 커스터마이징해 개선한 스토리지 엔진
  • TokuDB
    • Percona에서 개발중인 엔진

각 스토리지 엔진 비교

기능 MMAPv1 WiredTiger RocksDB TokuDB
잠금 수준 컬렉션 도큐먼트 도큐먼트 도큐먼트
데이터 구조 B-Tree B-Tree LSM Fractal-Tree
빌트인 캐시 X(운영체제 캐시를 사용) O O O
세컨드리 인덱스 O O O O
데이터 압축 X O O O
인덱스 압축 X O O O
암호화 X O X X
In-Memory 지원 X O X X
컬렉션 파티션 X X X O

스토리지 엔진 혼합 사용

  • 하나의 인스턴스에서 동시에 여러 스토리지 엔진은 사용 불가
  • 인스턴스만 다르면 다른 엔진 사용 가능. ex) 1번 샤드는 WiredTiger 스토리지 엔진 사용, 2번 샤드는 RocksDB 엔진 사용
  • MongoDB의 각 샤드와 레플리카 셋의 멤버들은 OpLog에 의해 동기화가 됨에 따라 사실상 각 멤버들의 스토리지 엔진에 의존적이지 않기 때문.

MMAPv1

  • 2.6까지는 데이터베이스 단위의 잠금 사용, 이후 3.0부턴 컬렉션 수준의 잠금으로 개선됨
  • 내장 캐시 기능이 없어 운영체제의 캐시를 활용 -> 시스템 콜을 활용해야 하기 때문에 오버헤드가 크고 페이지 관리나 더티페이지 관리가 안정적이지 못함
  • 데이터 파일은 데이터베이스 단위로 생성됨

MMAPv1 엔진 설정

  • 운영체제 캐시를 사용하므로 건들게 거의 없음. 거의 디스크 데이터 파일의 경로나 초기 크기 등을 결정하는 옵션, 리눅스 커널의 파라미터 튜닝이 더 많이 필요
  • 기본적으로 64MB, 128MB, ... , 2GB, 2GB, ... 순으로 데이터 파일이 생성 됨.
  • 이를 방지하려면 storage.smallFiles 옵션을 활성화시켜야 함 -> 16MB ~ 512MB 까지만 증가

MongoDB 서버 상태 확인

mongostat 명령어를 사용하면 서버의 쿼리 처리량, 메모리 사용량 등의 전체적인 상태를 한눈에 볼 수 있다.

flush : 몇 번이나 데이터 파일이 디스크에 동기화 됐는지
mapped : 데이터 파일이 리눅스의 페이지 캐시에 얼마나 매핑되어 있는지
vsize: 서버 프로세스가 현재 사용 중인 가상 메모리 공간의 크기
faults : 1초에 몇번이나 페이지 폴트가 발생했는지
locked db : 가장 잠금이 심한 데이터베이스

운영체제 캐시

  • 급작스럽게 다른 프로세스에서 메모리를 많이 요구하는 경우 리눅스 서버의 캐시 삭제 현상으로 인해 이미 로딩되어 있던 데이터가 날아가는 경우가 있음
  • 최적으로 운영하기 위해 리눅스 커널의 작동 방식과 파라미터 튜닝이 필수적임

페이지 캐시 데이터 읽고 쓰기


페이지 캐시의 데이터 읽기

리눅스의 디스크 읽기는 주변의 일부페이지들을 같이 읽어 들이는 Read-Ahead 방식이다. 이는 대량의 데이터를 읽을 때 유용한 방법인데, MongoDB 서버는 주로 랜덤 읽기 위주의 처리를 필요로 한다. 그래서 꼭 필요한 페이지만 메모리로 적재하면 된다.
일반적으로 리눅스의 Read-Ahead 설정은 128 ~ 256 정도인데 이렇게 되면 무조건 64 ~ 128KB 정도의 데이터를 읽어온다. 하지만, 필요한 데이터는 고작 4 ~ 8KB 정도이기 때문에 설정값을 변경해주는 것이 좋다. MMAPv1 스토리지 엔진의 인덱스는 8KB 단위의 페이지를 사용하므로, 디스크 읽기를 8KB에 맞춰야 한다. 결론적으로, 16 ~ 32 정도의 설정이 적절하다.
명령어 : blockdev --setra 16 /dev/sda


페이지 캐시의 데이터 읽기
사용자가 데이터를 변경하면 리눅스의 페이지 캐시 내용을 먼저 변경한다. 이렇게 되면 메모리 상의 데이터는 변경되었지만, 아직 디스크로 동기화되지 않은 페이지를 더티 페이지라고 한다.
만약, 이 상태에서 비정상 종료를 하게 되면 데이터는 영구적으로 손실된다. 따라서, 대부분의 데이터베이스는 WAL(Write Ahead Log)를 남겨 서버가 다시 시작되면 손상된 데이터를 복구한다.
변경내역을 바로바로 디스크에 저장하지 않는 이유는 더 많은 쓰기를 모아서 한번에 배치처리를 하기 위함이다. 리눅스 커널은 데이터 동기화를 얼마나 자주 실행할 것인지 조정할 수 있도록 몇 개의 파라미터를 제공하고 있다.

dirty_writeback_centisecs, dirty_expire_centisecs : 더티 페이지를 얼마나 자주 어떤 기준으로 디스크에 기록할 것인지
dirty_ratio, dirty_background_ratio : 페이지 캐시가 디스크로 기록되지 않은 더티 페이지를 얼마나 보유하도록 허용할 것인지
dirty_bites, dirty_background_bytes : 바이트 단위로 더티 페이지의 허용치를 결정

    ELO
    ELO

    티스토리툴바