키-값 구조로 저장 가능한 In-Memory 데이터 스토리지 입니다.
경쟁 제품인Memcached
대비 다양한 자료구조를 제공하는 것이 장점입니다.
한 마디로 캐시 메모리입니다.
트래픽이 높은 서비스를 다루고 있는 개발자라면 더욱 익숙한 용어일거 같은데요,
저도 업무에 쓰게 되어 열심히 배우고 있습니다. 💦
휘발성 메모리에 저장되다 보니, 중요한 데이터를 저장하기엔 무리가 있다고 생각했습니다.
갑자기 캐시 서버가 다운되거나 하면 다 날아가니까요(!)
하지만 쿠폰 지급 서비스에서 레디스가 단순 캐시를 넘어서 하나의 DB처럼 쓰이는걸 보고 생각이 많아졌습니다.
캐시 데이터에 의존하기엔 크리티컬해보이는데.. 어떻게 믿고 쓰는걸지 궁금했습니다.
이런 기술적 질문이 들때면 ChatGPT로 방향을 잡는 것이 편해졌습니다.ㅎㅎ
요약
질문
redis는 휘발성 메모리에 올라가는 스토리지인데, 어떻게 믿고 DB처럼 사용할 수 있는가?
답변
디스크에 데이터를 persist 해주는 기능이 있기 때문이다. 총 2가지가 있다.
1. snapshotting (RDB)
2. append-only file (AOF)
그러나 강한 데이터 내구성이 필요하거나,
복잡한 쿼리가 필요한 경우에는 Redis를 저장소로 쓰는걸 추천하지 않는다.
여기서 알 수 있는 점은,
Redis는 캐시로만 쓰이지 않습니다. 설정에 따라 저장소의 역할도 수행할 수 있습니다.
이 답변으로 주요 키워드를 알아냈고, 이를 설명하는 공식 문서를 찾을 수 있었습니다.
수많은 영어가 있지만(!) 한 번 따라가 봅시다.
RDB (Redis Database): RDB persistence performs point-in-time snapshots of your dataset at specified intervals.
AOF (Append Only File): AOF persistence logs every write operation received by the server. These operations can then be replayed again at server startup, reconstructing the original dataset. Commands are logged using the same format as the Redis protocol itself.
No persistence: You can disable persistence completely. This is sometimes used when caching.
RDB + AOF: You can also combine both AOF and RDB in the same instance.
크게 RDB
와 AOF
두 가지가 있습니다.
No persistence
를 보면 순수하게 캐시로만 쓰는 것도 가능하다는 걸 알 수 있습니다.
RDB (Redis Database): RDB persistence performs point-in-time snapshots of your dataset at specified intervals.
주의: 이 글에서 칭하는 RDB는 Relational Database 가 아닙니다
주기적으로 RDB의 스냅샷을 백업하고, 필요 시 특정한 시점의 스냅샷으로 롤업하는 방식입니다.
fork
해줄 뿐입니다. 때문에 부모 프로세스는 디스크 입출력을 수행하지 않습니다.fork()
속도가 느릴 수 있습니다. fork()
는 자식 프로세스가 디스크에 데이터를 영속화할 때 필요합니다. 데이터셋이 크거나 CPU 성능이 좋지 않을 경우 client 수신을 n초까지도 멈출 수 있습니다.AOF
도 로그파일 rewrite를 할 때 fork()
를 하지만 RDB
만큼 자주 하진 않으며, rewrite 정책도 설정이 가능하기 때문에 효율적입니다.AOF (Append Only File): AOF persistence logs every write operation received by the server. These operations can then be replayed again at server startup, reconstructing the original dataset. Commands are logged using the same format as the Redis protocol itself.
모든 쓰기 명령들을 특정한 로그 파일에 기록해둡니다. 이 데이터를 기반으로 서버 재시작/재구성 시 복구할 수 있습니다.
fsync(파일-장치 동기화)
정책을 다양하게 수립할 수 있습니다. 기본적으로는 1초마다 fsync
를 하는데, 여전히 준수한 쓰기 성능을 보입니다. 백그라운드 스레드로 동작하며, 메인 스레드는 fsync
가 진행 중이지 않을 때만 쓰기 명령을 받으려고 '노력'합니다. (100% 보장이 아니기 때문에, fsync
간격 간에 데이터 유실은 발생 가능합니다.)redis-check-aof-tool
이 복구해줄 수 있습니다.FLUSHALL
같은 명령으로 데이터를 전부 지웠다 하더라도, 로그 파일에 명령들이 다 남아있기 때문에 복구할 수 있습니다. (FLUSHALL
로그만 지우고 재시작하면 됩니다!)AOF
파일이 RDB
파일보다 큽니다.fsync
정책을 어떻게 가져가느냐에 따라 RDB
보다 느릴 수 있습니다. 쓰기 부하가 더 심한 편입니다.RDB
만 -> 장애 상황 시 몇 분 정도의 데이터는 유실되어도 상관 없는 경우AOF
만 -> 공식적으로는 권장하지 않습니다. (AOF 엔진의 버그 가능성이 언급됨)제 생각엔 '완벽하게' 지켜내는 솔루션은 없는거 같습니다. 설사 둘을 합쳐서 쓴대도요.
(오프더레코드지만, 그래도 요즘은 클라우드로 쉽게 scale-out이 가능하니.. 너무 집착하진 않아도 되지 않을까 싶습니다.)
하지만 최대한 수렴하게 할 순 있습니다.
AOF
의fsync
설정을always
로 가져간다면 모든 명령을 즉각 파일에 기록하게 됩니다. (성능이 느리므로 공식적으론 권장되지 않습니다.)
- 논리적으론 완벽하게 데이터를 지킬 수 있지만, 물리적으로는 100% 확신할 순 없습니다. (결국
fsync
도 운영체제 위에서 돌아가기 때문에 크래시 등 이슈가 생길 수 있기 때문입니다.)