레디스의 영속성에 해당되는 내용임.
레디스는 기본적으로 단일 스레드로 동작. 따라서 디스크 I/O와 같은 무거운 작업이 메인 스레드를 멈추게(Blocking) 하지 않도록 설계하는 것이 매우 중요. 레디스는 이를 위해 프로세스 분리(fork())와 제한적인 백그라운드 스레드를 활용
RDB(스냅샷) 방식
자식 프로세스를 통한 메인 스레드 보호방식인 RDB는 특정 시점의 데이터셋 스냅샷을 디스크에 저장합니다.
단점 및 한계
- 데이터셋이 매우 큰경우
fork() 를 수행하는 작업 자체에 시간이 꽤 소요될 수 있음
- 메인 스레드가 밀리초 단위에서 1초까지 클라이언트 요청 처리를 멈추는 현상이 발생할 수 있음
fork()시에 왜 메인 스레드에서 대기가 걸릴 수 있고 그 지연을 줄일 수 있는 방법은?
답: 페이지테이블
- 개념: 가상 메모리 주소를 실제 물리 메모리 주소로 매핑하기 위해 페이지 테이블이라는 지도를 관리함
- 발생 원인: fork()가 실행될 때, 실제 데이터(RAM의 내용)은 복사되지 않지만, 이 페이지 테이블은 프로세스로 그대로 복사되어야 함
- 지연 현상: Redis 인스턴스가 사용하는 메모리가 클수록 페이지 테이블의 크기도 커짐. (예시. 수십 GB 이상의 메모리를 사용하는 경우 이 테이블을 복사하는 작업 자체가 CPU를 점유하게 되며, 이 동안 Redis의 메인 스레드는 클라이언트의 요청을 처리하지 못하고 멈추게 됨)
- 해결 방법: 메모리를 작게 유지해야 복사 작업이 가벼워짐.
만약 자식 프로세스가 파일에 데이터를 쓰는 동안, 메인 스레드에서 새로운 데이터 변경 요청이 들어온다면?
핵심 키워드: 메모리 페이지(보통 4KB)를 복사하여 별도 공간 만듦
- 공유 메모리: 처음에는 부모와 자식이 같은 물리 메모리 페이지를 가리킴
- 수정 발생: 메인 스레드가 어떤 데이터를 수정하려고 하면, 운영체제는 해당 데이터가 포함된 메모리 페이지를 복사하여 별도의 공간을 만듦
- 격리: 메인 스레드는 복사된 새로운 페이지에 데이터를 쓰고, 자식 프로세스는 여전히 원본 페이지를 보며 RDB를 만듦
생각할 부분: 메인 스레드에 많은 양의 쓰기 작업이 들어오면, 메모리 페이지 복사가 빈번하게 일어나서 전체 메모리 사용량이 순식간에 2배 가까이 급증할 수 있음