공식문서로 알아보는 Redis persistence
개요
Redis는 In-memory 시스템으로 동작하지만 disk에 영구저장하는 기능도 지원합니다.
어떤 방식으로 저장하는지에 대해 Redis 공식문서를 기반으로 Redis Persistence에 대해 알아보고자 합니다.
Redis는 어떻게 데이터를 disk에 저장할까?
Persistence란 SSD와 같은 내구성 있는 스토리지에 데이터를 기록하는 것을 의미합니다.
Redis는 이에 대해 다양한 방법론을 제시합니다.
- Redis DataBase(RDB) : 지정된 간격으로 데이터 집합의 특정 시점 스냅숏을 저장합니다.
- Append Only File(AOF) : 모든 write operation을 기록하고, 서버 시작 시 원래 데이터세트를 재구성할 수 있습니다.
- No Persistence : 지속성을 완전히 비활성화할 수 있습니다.
- Redis Database + Append Only File(RDB + AOF) : 위의 둘 방식을 결합한 방식입니다.
AOF방식 예시 그림
insert, update delete 명령에 대해 모두 기록합니다.
RDB 방식 예시그림
특정 주기로 스냅숏을 저장합니다.
Redis DataBase(RDB)의 장점과 단점
장점들
- 지정된 간격으로 데이터 집합의 특정 시점의 스냅숏을 저장하기 때문에 백업에 적합하고, 장애가 발생했을 시 복구에 유용합니다.
- 큰 데이터가 존재할때 Append Only File에 비해 더 빠르게 재시작할 수 있습니다.
단점들
- 특정 주기(예: 5분)으로 저장하기 때문에 몇 분 간의 데이터를 손실할 수 있습니다.
- 자식 프로세스를 사용하여 디스크에 저장하기 위해 자주 fork를 수행합니다, 데이터 집합이 매우 크고 CPU 성능이 좋지 않다면 1초까지 클라이언트 서비스를 중단할 수 있습니다. (물론 AOF도 fork를 수행하지만 그 빈도가 적습니다.)
Append Only File의 장점과 단점
장점들
- 동기화 정책을 다양하게 가져갈 수 있습니다 (동기화 수행 안 함, 매초마다 동기화, 모든 쿼리마다 동기화), fsync를 사용하며 백그라운드 스레드를 사용하기 때문에 쓰기 성능이 우수합니다 - 권장옵션은 매초마다 동기화
- 로그 파일이기 때문에 정전이 발생해도 손상되지 않으며, redis-check-aof 도구를 활용하여 손상 시에도 문제를 쉽게 고칠 수 있습니다.
- FLUSHALL 명령어로 모든 데이터를 날리더라도 로그에서 최신 명령을 제거하고 Redis를 다시 시작하면 데이터 세트를 복구할 수 있습니다.
단점들
- 모든 이벤트를 기록하기 때문에 동일한 데이터라고 가정했을 때 Redis database 파일보다 더 큽니다.
- 동기화 정책에 따라 AOF가 더 느릴 수 있습니다, 일반적으로 매초로 설정하는 경우 성능은 더 높습니다.
무엇을 사용해야 할까?
일반적으로 두 가지 방법을 모두 사용하는 경우에는 PostgreSQL이 제공하는 수준으로 데이터 안정성을 원하는 경우입니다.
데이터를 중요하게 생각하지만 재해 발생 시 몇 분간의 데이터 손실도 감수할 수 있는 경우에는 Redis Database만 사용해도 됩니다.
AOF만 사용하기도 하지만, 데이터베이스 백업, 빠른 재시작, AOF 엔진의 버그 발생 시를 대비하여 수시로 RDB 스냅숏을 생성하는 것이 좋기 때문에 권장되지 않습니다.
즉, Redis DataBase를 우선적으로 검토하고 필요시에는 Append Only File과 함께 사용하는 것이 좋다!
스냅숏
기본적으로 Redis는 스냅숏을 dump.rdb라는 바이러니 파일으로 디스크에 저장합니다.
SAVE 또는 BGSAVE 명령으로 수동으로 호출할 수 있습니다.
스냅숏 어떻게 동작할까?
1. Redis가 fork 되어 자식과 부모 프로세스가 생깁니다, fork란 현재 프로세스의 복사본을 생성하여 멀티태스킹과 동시성을 구현하는 데 사용됩니다.
2. 자식은 임시 RDB파일에 데이터세트를 쓰기 시작합니다.
3. 새로운 RDB 파일 쓰기가 완료되면 이전 파일을 대체합니다.
Log rewriting
쓰기 작업이 수행될수록 AOF 파일은 점점 더 커지게 됩니다.
이때 Redis는 클라이언트에 대한 서비스를 중단하지 않고 백그라운드에서 AOF 파일을 다시 작성할 수 있는 기능을 제공합니다.
AOF 파일이 오류로 truncated 되었다면(잘려있다면)?
* Reading RDB preamble from AOF file...
* Reading the remaining AOF tail...
# !!! Warning: short read while loading the AOF file !!!
# !!! Truncating the AOF at offset 439 !!!
# AOF loaded anyway because aof-load-truncated is enabled
AOF 파일을 작성하는 동안 서버가 죽었거나, AOF 파일이 저장된 DISK의 용량이 꽉 찼을 때 AOF의 마지막 명령이 잘릴 수 있습니다.
최신 버전에서는 마지막 명령만 제거하고 AOF를 로드할 수 있습니다.
이때 서버는 위와 같은 로그를 출력합니다.
원하는 경우 이때 Redis가 강제로 중지되도록 설정을 구성할 수 있지만, 기본구성은 재시작 후 가용성을 보장하기 위해 계속 진행하도록 되어 있습니다.
$ redis-check-aof --fix <filename>
예전 버전의 Redis는 자동으로 복구되지 않을 수 있으며, redis-check-aof를 활용하여 파일을 수정하고 재시작을 수행해야 합니다.
AOF 파일이 잘려있는 것뿐만 아니라, 중간에 바이트 시퀀스가 손상된 경우
* Reading the remaining AOF tail...
# Bad file format reading the append only file: make a backup of your AOF file, then use ./redis-check-aof --fix <filename>
이런 경우 상황은 더 복잡해지고, Redis는 실행할 때 에러로그와 함께 중단됩니다.
가장 좋은 방법은 --fix 옵션 없이 redis-check-aof를 실행하고 문제를 파악하고 지정된 오프셋으로 이동하여 파일을 수동으로 복구할 수 있는지 확인해야 합니다.
redis-check-aof가 해결하도록 할 수 있지만, 유효하지 않은 부분부터 파일 끝까지 모든 AOF가 폐기되어 손상이 파일의 초기에 발생한 경우 엄청난 양의 데이터 손실이 발생할 수 있습니다.
정리 후 드는 생각
Redis Persistence를 공부해 보았을 때 장애가 발생했을 때 AOF 파일 등이나 RDS등에서도 데이터 유실이 될 가능성도 존재합니다.
하지만 Redis를 Cache용도로 사용한다면 이미 실제 DB에 데이터가 저장되어 있을것이고, 다시 Load 해서 캐시를 쌓으면 될 것 같습니다.
만약 Redis Persistence까지 고려해야 한다면, 아마도 Redis를 주력 저장소 느낌으로 사용하는 것 같습니다.
이런 상황이면 비슷하게 사용할 수 있는 Hazelcast와 잘 비교해서 사용하면 좋을 것 같습니다.
이때 장애가 발생하고 RDS 덤프와 AOF 파일을 분석하는것도 중요하겠지만 장애자체를 대비하여 고가용성을 고려하거나, DISK 용량을 잘 모니터링해서 가득 차지 않도록 주의해야 할 것 같습니다.
참고자료
https://redis.io/docs/management/persistence/