레디스는 인메모리 데이터베이스로, 매우 빠른 성능을 제공하지만 서버가 재시작되거나 종료되면 데이터가 휘발된다는 단점이 있다.
따라서 레디스는 데이터를 안전하게 보존하고 유지하려면 디스크에 데이터를 저장하여 백업하는 방법이 필요하다.
이를 위해 레디스는 두 가지 영속화 옵션으로 RDB 방식과 AOF 방식을 제공한다.
RDB
RDB은 Redis Database File 약자로, 특정 시점의 데이터를 덤프 파일로 저장하는 방식이다. 재시작 시 덤프 파일을 통해 데이터를 복구한다.
RDB 방식은 장점으로는
- 스냅샷한 데이터 외의 부가적인 데이터가 없기 때문에 작은 파일 사이즈로 백업 파일 관리가 용이하다.
- 파일 사이즈가 작기 때문에 원격지 백업, 버전 관리가 가능하다.
- fork를 이용해 백업을 하기 때문에 서비스 중인 프로세스의 성능에는 영향이 없다.
- 빠른 복구가 가능하다.
단점으로는
- 스냅샷을 저장하는 시점 사이의 데이터 변경 사항은 유실이 있을 수 있다.
- fork를 이용하기 때문에 시간이 오래 걸릴 수 있고, CPU와 메모리 자원을 많이 소모한다.
따라서, 데이터 무결성이나 정합성에 대한 요구가 크지 않는 경우에 사용 가능하다.
RDB에 대한 설정값 (redis.conf)
https://raw.githubusercontent.com/redis/redis/unstable/redis.conf
레디스 설정 파일 (redis.conf)을 확인할 수 있다
우선 설정 파일이 없어도 기본적으로 RDB 방식이 활성화되어 있다. 설정 파일을 확인해 보면
- save 3600 1: 1시간(3600초) 동안 데이터가 1번 이상 변경되면 스냅샷을 생성
- save 300 100: 5분(300초) 동안 데이터가 100번 이상 변경되면 스냅샷을 생성
- save 60 10000: 1분(60초) 동안 데이터가 10,000번 이상 변경되면 스냅샷을 생성
따라서 레디스는 자동으로 특정 주기에 따라 백업 파일을 생성하여 현재 상태를 백업하게 된다.
위 설정에 따라서, 1시간 내에 데이터가 1회 이상 변경되는 경우, 5분 내에 데이터가 100회 이상 변경되는 경우, 1분 내에 데이터가 10,000회 이상 변경되는 경우 백업을 하게 된다.
만일 이를 비활성화하고 싶은 경우 save "" 으로 설정하여 RDB 스냅샷 기능을 비활성화할 수 있다.
또 다른 설정값으로는
(1) stop-writes-onbgsave-error
: RDB 파일 저장이 실패했을 때, 레디스가 추가적인 쓰기 작업을 중지할지에 대한 여부를 설정한다.
yes : 백업 오류가 발생하면 쓰기 작업을 중단하여 데이터 무결성을 유지한다.
no : 백업 오류가 발생하더라도 쓰기 작업을 계속 진행하여 일부 데이터 무결성 위험은 있지만, 레디스는 중단하지 않는다.
(2) rdbcompression yes
: RDB 스냅샷 파일을 압축하여 저장할지를 결정한다.
yes : RDB 파일을 압축하여 저장한다. 압축을 통해 디스트 공간은 절약할 수 있지만 CPU 사용량은 증가할 수 있다.
no : RDB 파일을 압축하지 않고 저장한다. CPU 부담은 줄일 수 있지만, 더 많은 디스크 공간이 필요하다.
(3) rdbchecksum yes
: RDB 파일에 대한 체크섬을 추가할지에 대한 여부를 설정한다.
yes : RDB 파일의 무결성을 확인할 수 있도록 체크섬을 추가하여, 레디스가 RDB 파일을 로드할 때 데이터 오류를 감지할 수 있다.
no : 체크섬을 추가하지 않아, 데이터 복구 과정은 조금 빨라지지만, 오류 검출 기능은 비활성화된다.
(4) dbfilename dump.rdb
: 저장될 RDB 파일의 이름을 지정하는 옵션이다.
(5) rdb-del-sync-files
: RDB 파일을 삭제하는 방식에 영향을 주는 설정값이다.
yes : 레디스가 RDB 파일을 삭제할 때 OS의 synchronous 방식으로 처리하여 데이터의 확실한 삭제를 보장한다.
no : 기본값으로, 비동기 방식으로 파일을 삭제하여 성능은 빠르지만, 시스템 충돌 시 완전한 파일 삭제가 보장되지 않을 수 있다.
(6) dir ./
: RDB 파일을 저장할 디렉터리를 지정한다.
RDB 저장 시점
RDB 저장 방식에는 SAVE와 BGSAVE 방식이 존재한다.
SAVE는 순간적으로 레디스의 동작을 정지시키고 스냅샷을 디스크에 저장한다. (blocking 방식)
- 메인 프로세스만 사용하므로 별도의 자식 프로세스 관리가 필요 없어 단순하고 추가 메모리를 사용하지 않는다.
- 하지만 SAVE 명령어 실행 중에는 레디스가 다른 요청을 처리하지 못해 순간 서비스 중단이 발생할 수 있다.
- 대규모 데이터 저장소에서는 실행 시간이 길어져 서비스 중단이 길어질 수 있어, 실시간 시스템에는 적합하지 않습니다.
1) 주 프로세스가 데이터를 새로운 RDB 파일에 저장한다.
2) 모든 데이터 쓰기가 끝나면 기존 RDB 파일을 삭제하고 새로운 RDB 파일로 교체한다.
BGSAVE는 백그라운드 SAVE라는 의미로, 별도의 자식 프로세스를 띄운 후 명령어 수행 당시의 스냅샷을 디스크에 저장하여 레디스 동작을 멈추지 않게 한다. (non-blocking 방식)
- 자식 프로세스가 백업을 수행하므로 메인 프로세스는 요청을 처리할 수 있어 서비스 중단 없이 백업이 가능하다.
- 따라서 실시간 시스템에 적합하다.
- 하지만 자식프로세스를 생성할 때 메모리를 복제하여 메모리 사용량이 크게 증가할 수 있다.
1) 자식 프로세스를 생성하기 위해 fork()를 호출하여 프로세스를 복제한다.
2) 새로 생성된 자식 프로세스가 데이터를 새로운 RDB 임시 파일에 작성한다.
3) 모든 데이터 쓰기가 끝나면 기존 RDB 파일을 삭제하고, 새 임시 파일의 이름을 RDB 파일로 변경하여 교체합니다.
AOF
AOF는 Append Only File 약자로, 모든 쓰기 연산을 순차적으로 파일에 기록하는 방식이다. 재시작 시 AOF에 기록된 모든 연산을 재수 행하여 데이터를 복구한다.
AOF 방식은 장점으로는
- 모든 변경사항을 기록하기 때문에 안정적으로 데이터를 백업할 수 있다.
- append-only 방식이므로 백업 파일이 손상될 위험이 적다.
- 실제 수행된 명령어가 저장되어 있으므로 개발자가 보고 이해할 수 있고 수정도 가능하다.
단점으로는
- 모든 히스토리가 저장되기 때문에 RDB 백업 파일 보다 파일 사이즈가 크다.
- RDB 방식 대비 백업과 복구 속도가 느리다.
따라서, 데이터 무결성이나 정합성이 중요한 경우에 사용 가능하다.
AOF에 대한 설정값 (redis.conf)
https://raw.githubusercontent.com/redis/redis/unstable/redis.conf
레디스 설정 파일 (redis.conf)을 확인할 수 있다.
설정파일을 보면 기본적으로 appendonly no으로 설정되어 있기 때문에 RDB 방식으로 활성화되어 있다.
따라서 AOF 방식을 사용하기 위해서는 appendonly yes로 설정해야 한다.
(1) appendfilename "appendonly.aof"
: AOF 파일 이름을 지정한다.
(2) appenddirname "appendonlydir"
: AOF 파일을 저장할 디렉터리 이름을 지정한다.
(3) appendfsync
: appendonly 파일에 데이터를 기록하는 시점을 설정한다.
always : 쓰기 연산이 발생할 때마다 AOF 파일에 즉시 동기화한다. 가장 안전하지만 가장 느리다.
everysec : 1초마다 AOF 파일에 기록한다. 적절한 성능과 안정성을 유지할 수 있는 옵션이다. (권장)
no : 기록하는 시점을 OS가 정한다. 일반적으로 리눅스는 30초로 데이터 유실이 발생할 수 있다.
AOF의 Rewite
* 아래 설정은 AOF의 Rewite 설정과 관련이 있다.
rewrite 란 AOF 파일이 특정 조건일 때, 최소한의 로그만 남기기 위해 일부를 새로 쓰는 방법이다.
예를 들어 1개의 키값을 100번 SET해도 최종으로 해당 키에 대한 값은 1개이므로 이는 하나의 SET으로 대체가 가능하다.
(4) no-appendfsync-on-rewrite no
: rewrite 하는 동기화 방식을 설정한다.
yes : AOF 재작성 중에 appendfsync 설정을 무시하고 동기화를 중단하여 성능을 높입니다. 하지만 이 설정은 데이터 안전성에 다소 영향을 줄 수 있습니다.
no : 기본값으로, AOF 재작성 중에도 appendfsync 설정을 유지하여 데이터 손실 위험을 줄입니다.
(5) auto-aof-rewrite-percentage 100
: 자동 재작성 기준을 파일 사이즈에 대한 퍼센트로 설정한다.
값이 100으로 설정되어 있으면, 레디스 서비가 시작되었을 시점의 AOF 파일 사이즈보다 현재 AOF 파일 사이즈가 100%, 즉 2배 이상 증가했을 때 자동으로 rewrite가 동작한다.
(6) auto-aof-rewrite-min-size 64mb
: 자동 재작성 기준을 최소 파일 크기로 설정한다. 설정한 크기보다 작은 AOF 파일은 rewrite가 동작하지 않는다.
기본값이 64MB으로, AOF 파일이 최소 64MB 이상이어야만 rewrite가 동작한다.
(7) aof-load-truncated yes
: 레디스 서버가 시작될 때, 손상된 AOF 파일을 자동으로 복구할지 여부를 설정한다.
yes: Redis가 시작할 때 AOF 파일이 손상된 경우, 손상된 부분을 잘라내고 나머지 부분을 로드한다. 서버가 비정상 종료된 후 빠르게 복구될 수 있도록 돕는다.
no: 손상된 AOF 파일이 발견되면 Redis는 복구를 시도하지 않고 서버 시작을 중단한다.
(8) aof-use-rdb-preamble yes
: AOF 파일에 RDB 프리앰블을 사용할지 설정하는 옵션이다.
yes: Redis는 AOF 파일에 RDB 스냅샷을 포함하여, AOF 파일의 로딩 속도를 높인다. 초기 로딩 시간이 짧아지고, 메모리 사용을 줄일 수 있다.
no: Redis는 순수하게 AOF 명령어만을 사용하여 데이터를 복구한다.
(9) aof-timestamp-enabled no
: AOF 파일에 타임스탬프를 포함할지 여부를 설정하는 옵션이다.
yes: 각 AOF 파일의 명령어에 타임스탬프를 기록하여, 파일이 복구될 때 각 명령이 실행된 시점을 알 수 있다.
no: 기본값으로, 타임스탬프를 추가하지 않는다. AOF 파일 크기를 줄 수 있다.
RDB와 AOF 선택 기준
위에서 살펴봤듯이, RDB 방식과 AOF 방식의 장단점은 명확하다.
RDB 은 성능은 좋지만, 데이터 유실의 가능성이 존재한다.
AOF 은 성능은 떨어지지만, 데이터 유실이 거의 발생하지 않는다.
따라서 백업은 필요하지만, 어느 정도의 데이터 손실이 발생해도 괜찮은 경우라면 RDB 방식을 사용하는 것이 적절하다.
redis.conf 파일에서 SAVE 옵션을 적절하게 변경하면 된다.
하지만, 데이터 손실 없이 모든 데이터가 보장되어야 할 경우라면 AOF 방식을 사용하는 것이 바람직하다.
또한 RDB와 AOF를 함께 사용하여 각 방식의 장점을 극대화할 수 있다.
RDB는 주기적으로 백업하면서, AOF는 실시간 변경사항을 기록하도록 설정하여 데이터 복구와 안정성 간의 균형을 맞출 수 있다.
이렇게 하면 서버가 재시작될 때 백업된 스냅샷으로 백업하고, 비교적 적은 양의 AOF 로그만 재실행하면 되기 때문에, 성능도 보장하고 데이터 유실도 방지할 수 있다.
참고
- https://redis.io/docs/latest/operate/oss_and_stack/management/config/
- https://inpa.tistory.com/entry/REDIS-%F0%9F%93%9A-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%98%81%EA%B5%AC-%EC%A0%80%EC%9E%A5%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95-%EB%8D%B0%EC%9D%B4%ED%84%B0%EC%9D%98-%EC%98%81%EC%86%8D%EC%84%B1
- https://gencomi.tistory.com/entry/Redis-%EB%B0%B1%EC%97%85
'정리' 카테고리의 다른 글
분산 메시지 큐 이해하기: 가상 면접 사례로 배우는 대규모 시스템 설계 기초 2 (0) | 2024.11.04 |
---|---|
[Redis] Redis 캐싱 전략 패턴 정리 (0) | 2024.10.20 |
[친절한 SQL 튜닝] NL 조인, 소트 머지 조인, 해시 조인 (2) | 2024.06.16 |
[친절한 SQL 튜닝] 인덱스 튜닝 (2) : 인덱스 스캔 효율화, 인덱스 설계 (0) | 2024.06.13 |
[친절한 SQL 튜닝] 인덱스 튜닝 (1) 테이블 액세스 최소화, 부분범위 처리 활용 (1) | 2024.05.05 |