휘발성 DB인 Redis, 어떻게 믿고 쓰는걸까?

숑숑·2023년 3월 8일
5

DB

목록 보기
5/7
post-thumbnail

✨ Redis란?

키-값 구조로 저장 가능한 In-Memory 데이터 스토리지 입니다.
경쟁 제품인 Memcached 대비 다양한 자료구조를 제공하는 것이 장점입니다.

한 마디로 캐시 메모리입니다.

트래픽이 높은 서비스를 다루고 있는 개발자라면 더욱 익숙한 용어일거 같은데요,
저도 업무에 쓰게 되어 열심히 배우고 있습니다. 💦

휘발성 메모리에 저장되다 보니, 중요한 데이터를 저장하기엔 무리가 있다고 생각했습니다.
갑자기 캐시 서버가 다운되거나 하면 다 날아가니까요(!)

하지만 쿠폰 지급 서비스에서 레디스가 단순 캐시를 넘어서 하나의 DB처럼 쓰이는걸 보고 생각이 많아졌습니다.
캐시 데이터에 의존하기엔 크리티컬해보이는데.. 어떻게 믿고 쓰는걸지 궁금했습니다.


🤷‍♀️ 어떻게 믿고 저장소로 쓰는가?

이런 기술적 질문이 들때면 ChatGPT로 방향을 잡는 것이 편해졌습니다.ㅎㅎ

요약
질문
redis는 휘발성 메모리에 올라가는 스토리지인데, 어떻게 믿고 DB처럼 사용할 수 있는가?
답변
디스크에 데이터를 persist 해주는 기능이 있기 때문이다. 총 2가지가 있다.
1. snapshotting (RDB)
2. append-only file (AOF)
그러나 강한 데이터 내구성이 필요하거나,
복잡한 쿼리가 필요한 경우에는 Redis를 저장소로 쓰는걸 추천하지 않는다.

여기서 알 수 있는 점은,
Redis는 캐시로만 쓰이지 않습니다. 설정에 따라 저장소의 역할도 수행할 수 있습니다.

이 답변으로 주요 키워드를 알아냈고, 이를 설명하는 공식 문서를 찾을 수 있었습니다.
수많은 영어가 있지만(!) 한 번 따라가 봅시다.


Redis Persistence

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.

크게 RDBAOF 두 가지가 있습니다.
No persistence 를 보면 순수하게 캐시로만 쓰는 것도 가능하다는 걸 알 수 있습니다.

RDB (Redis Database)

RDB (Redis Database): RDB persistence performs point-in-time snapshots of your dataset at specified intervals.

주의: 이 글에서 칭하는 RDB는 Relational Database 가 아닙니다

주기적으로 RDB의 스냅샷을 백업하고, 필요 시 특정한 시점의 스냅샷으로 롤업하는 방식입니다.

장점

  • 장애 복구에 유용합니다.
  • 단일 파일이기 때문에 원격 데이터 센터(Amazon S3 등)으로 전송이 쉽습니다.
  • 큰 데이터셋에도 AOF보다 더 빠르게 재시작할 수 있습니다.
  • Redis 부모 프로세스가 할 일이 적습니다. 스냅샷을 생성해줄 자식 프로세스를 fork해줄 뿐입니다. 때문에 부모 프로세스는 디스크 입출력을 수행하지 않습니다.

단점

  • 데이터 유실이 생길 수 있습니다. 마지막 스냅샷 시간 ~ 장애 발생 시간 사이의 텀이 존재하기 때문입니다.
  • fork() 속도가 느릴 수 있습니다. fork()는 자식 프로세스가 디스크에 데이터를 영속화할 때 필요합니다. 데이터셋이 크거나 CPU 성능이 좋지 않을 경우 client 수신을 n초까지도 멈출 수 있습니다.
  • AOF도 로그파일 rewrite를 할 때 fork()를 하지만 RDB만큼 자주 하진 않으며, rewrite 정책도 설정이 가능하기 때문에 효율적입니다.

AOF (Append Only File)

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이 복구해줄 수 있습니다.
  • AOF 파일이 너무 길어지면 메모리가 부족해질 수 있으므로, 특정 조건에 따라 파일을 rewrite 해줄 수 있습니다.
  • 로그가 이해하기 쉽게 작성되어있습니다. 설령 FLUSHALL 같은 명령으로 데이터를 전부 지웠다 하더라도, 로그 파일에 명령들이 다 남아있기 때문에 복구할 수 있습니다. (FLUSHALL 로그만 지우고 재시작하면 됩니다!)

단점

  • 같은 데이터셋일 때, AOF 파일이 RDB 파일보다 큽니다.
  • fsync 정책을 어떻게 가져가느냐에 따라 RDB 보다 느릴 수 있습니다. 쓰기 부하가 더 심한 편입니다.

그럼 뭘 쓰면 되는데?

  • 둘 다 -> 일반적인 DB와 비슷한 수준의 데이터 안전을 원할 경우에 쓰면 됩니다.
  • RDB만 -> 장애 상황 시 몇 분 정도의 데이터는 유실되어도 상관 없는 경우
  • AOF만 -> 공식적으로는 권장하지 않습니다. (AOF 엔진의 버그 가능성이 언급됨)

🤔 그래서, 데이터 유실 0%가 가능한가?

제 생각엔 '완벽하게' 지켜내는 솔루션은 없는거 같습니다. 설사 둘을 합쳐서 쓴대도요.
(오프더레코드지만, 그래도 요즘은 클라우드로 쉽게 scale-out이 가능하니.. 너무 집착하진 않아도 되지 않을까 싶습니다.)

하지만 최대한 수렴하게 할 순 있습니다.

AOFfsync 설정을 always 로 가져간다면 모든 명령을 즉각 파일에 기록하게 됩니다. (성능이 느리므로 공식적으론 권장되지 않습니다.)

  • 논리적으론 완벽하게 데이터를 지킬 수 있지만, 물리적으로는 100% 확신할 순 없습니다. (결국 fsync도 운영체제 위에서 돌아가기 때문에 크래시 등 이슈가 생길 수 있기 때문입니다.)

Reference

profile
툴 만들기 좋아하는 삽질 전문(...) 주니어 백엔드 개발자입니다.

0개의 댓글