본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성하였습니다.
강의 후기
오늘은 대용량 트래픽 시스템에서 필수적으로 활용되는 Redis의 기본 개념과 내부 동작 원리를 학습했다. Redis는 단순히 캐시 저장소로만 알려져 있지만, 실제로는 분산 환경에서 세션 스토어, 리더보드, Pub/Sub 메시징 등 다양한 용도로 활용되는 인메모리 데이터베이스다. 레디스 싱글 스레드 기반의 처리와 영속성에 관련해서 간단하게 알 수 있었다. 따라서 레디스의 핵심 특징을 추가적으로 살펴보기로 했다.
레디스의 핵심 특징
Redis는 모든 데이터를 메모리(RAM)에 저장하는 인메모리 아키텍처를 채택한다. 이는 전통적인 DBMS가 디스크 접근에 의존하는 것과 대조적이다. 디스크 I/O의 레이턴시가 밀리초 단위인 반면, 메모리 접근은 마이크로초 단위로 처리되기 때문에 수천 배의 성능 차이가 발생한다. 다만 전체 데이터 크기가 메모리 용량에 제한되며, 메모리 부족 시 정책에 따라 데이터가 제거될 수 있다는 한계가 있다.
Redis는 캐시 외에도 리더보드, 세션 스토어, 메시지 큐 등 다양한 시나리오에서 활용된다. 데이터 타입도 단순 String뿐만 아니라 List, Set, Sorted Set, Hash 등을 지원하여 복잡한 자료구조를 메모리에서 직접 다룰 수 있다.
영속성 측면에서는 RDB와 AOF 두 가지 메커니즘을 제공한다. RDB는 특정 시점의 스냅샷을 저장하는 방식으로 복구 속도가 빠르지만 마지막 스냅샷 이후 데이터가 손실될 수 있다. AOF는 모든 쓰기 작업을 로그로 기록하여 데이터 손실을 최소화하지만 파일 크기가 커지고 복구 시간이 길어질 수 있다. 두 방식의 장단점을 고려해 상황에 맞게 선택하거나 혼합 사용하는 것이 일반적이다.
Single Thread Event Loop의 동작 원리
Redis가 단일 스레드로 높은 성능을 낼 수 있는 비결은 이벤트 루프와 IO Multiplexing을 활용한 아키텍처에 있다. 일반적으로 단일 스레드는 한 번에 하나의 작업만 처리하기 때문에 동시성이 떨어질 것으로 예상되지만, Redis는 OS 수준의 이벤트 감지 시스템을 통해 이를 극복한다.
OS 수준 이벤트 감지 시스템
동작 과정을 살펴보면,
- 먼저 클라이언트들의 요청이 들어오면 OS 수준 이벤트 감지 시스템(epoll, kqueue 등)이 수천개의 클라이언트 연결 상태를 비동기적으로 감지한다.
- 이러한 읽기/쓰기 이벤트 이벤트들은 이벤트 큐에 등록되고
- 단일 스레드의 이벤트 루프가 이를 순차적으로 처리한다. 각 이벤트 처리는 마이크로초 단위로 빠르게 완료되므로, 실제로는 여러 클라이언트의 요청을 동시에 처리하는 것처럼 보인다.
IO Multiplexing
Multiplexing 방식의 핵심은 하나의 자원(채널, 장치, 스레드)을 통해 여러 개의 데이터 흐름을 동시에 처리하는 기술적 개념이다. 클라이언트 I/O 이벤트를 감지해 이벤트 큐에 등록하고, Redis의 단일 스레드는 해당 큐에서 명령을 꺼내 순차적으로 처리 결과를 생성한다. 여러 클라이언트의 요청을 한 개의 스레드가 관리하면서도 각 요청이 독립적으로 처리되는 구조다.
Threaded I/O
Redis 6.0부터는 네트워크 I/O 처리를 위한 멀티스레드가 도입되었다. 중요한 점은 명령 실행 자체는 여전히 메인 스레드에서만 수행된다는 것이다. I/O 스레드는 클라이언트 요청을 읽고 파싱하는 부분과 응답을 네트워크로 전송하는 부분만 담당한다. 이로써 명령 실행의 원자성(Atomic)은 유지하면서도 네트워크 I/O 병목을 해소해 전체 처리량을 향상시킬 수 있다.
영속성 메커니즘
인메모리 데이터베이스의 근본적인 문제는 서버 재시작 시 모든 데이터가 휘발된다는 점이다. Redis는 이를 해결하기 위해 RDB와 AOF 두 가지 영속성 메커니즘을 제공한다.
RDB(snapshot 방식)
RDB는 특정 시점의 전체 데이터 스냅샷을 디스크에 저장하는 방식이다. 복구 속도가 빠르고 파일 크기가 작다는 장점이 있지만, 스냅샷 저장 간격 사이에 발생한 데이터는 손실될 수 있다. 대용량 데이터셋에서 스냅샷 생성 시 성능 영향도 고려해야 한다.
AOF(Append Only File)
AOF는 모든 쓰기 명령을 순차적으로 로그 파일에 기록한다. 데이터 손실을 최소화할 수 있지만, 로그 파일이 계속 커지며 복구 시간이 길어진다는 단점이 있다. AOF rewrite 기능으로 파일 크기를 최적화할 수 있지만, 이 작업 자체도 시스템 리소스를 소비한다.
적용 판단은 데이터의 중요도와 시스템 특성에 따라 선택하면 좋을 것이다. 데이터 손실이 치명적인 경우 AOF를 사용하고, 성능이 최우선이며 일부 데이터 손실을 감수할 수 있다면 RDB를 선택한다. 단순 캐시라면 두 가지 모두 사용하지 않을수도, 두 방식을 함께 사용하는 하이브리드 방식을 사용하여 각각의 장점을 취할 수도 잇을 것이다.
참고 출처
- https://medium.com/better-programming/internals-workings-of-redis-718f5871be84
- 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#rdb_snapshotting_%EB%B0%A9%EC%8B%9D
- https://charsyam.wordpress.com/2020/05/05/%EC%9E%85-%EA%B0%9C%EB%B0%9C-redis-6-0-threadedio%EB%A5%BC-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90/



