Redis는 왜 싱글 스레드일까?
Redis는 왜 멀티 코어 시대에 싱글 스레드를 고집할까?
Redis를 공부하다가 이런 의문이 들었다.
내가 쓰는 노트북(M3 Air)만 해도 CPU 코어가 8개인데,
왜 Redis는 싱글 스레드로 동작하도록 설계됐을까?
“성능을 높이려면 멀티 스레드를 써서 CPU를 풀로 돌리는 게 맞지 않나?”
조금 더 파보니, Redis는 단순히 기술이 부족해서가 아니라
의도적으로 싱글 스레드를 선택했다는 걸 알게 됐다.
1. Redis의 병목은 CPU가 아니다
Redis가 싱글 스레드를 선택한 가장 큰 이유는
애초에 Redis의 성능 병목 지점이 CPU가 아니기 때문이다.
Redis는 In-Memory 데이터베이스다.
디스크가 아니라 메모리에 데이터를 읽고 쓰고,
연산 자체도 굉장히 단순하다.
즉,
- CPU 연산 → 매우 빠름
- 메모리 접근 → CPU 연산에 비해 상대적으로 느림
- 네트워크 I/O → 더 느림
CPU는 이미 충분히 빠르다.
Redis 공식 문서에 따르면,
Redis는 리눅스 환경에서 초당 수십만 ~ 백만 건 이상의 요청을 처리할 수 있다.
이 시점에서 CPU는 이미 “할 만큼 다 했다”는 상태다.
그럼 진짜 병목은 어디일까?
바로 메모리 접근과 네트워크 I/O다.
간단히 비유하면 이런 느낌이다.
- CPU: “계산 끝났어. 다음 작업 줘.” (대기 중)
- 네트워크: “잠깐만… 패킷 아직 오는 중이야.”
아무리 CPU를 더 빠르게 만들어도,
출근길 도로(네트워크)가 막혀 있으면 속도는 안 빨라진다.
그래서 Redis는 굳이 CPU 병렬 처리에 집착할 필요가 없었던 것이다.
2. 멀티 스레드의 비용: 컨텍스트 스위칭
그럼 이런 생각이 든다.
“그래도 멀티 스레드를 쓰면 더 빨라지는 거 아닌가?”
문제는 멀티 스레드에는 비용이 따른다는 것이다.
대표적인 게 컨텍스트 스위칭(Context Switching)이다.
싱글 스레드
→ 작업자 1명이 계속 일을 처리함 (전환 비용 없음)멀티 스레드
→ 작업자 A를 멈추고, 작업자 B를 실행함
이때 CPU는 단순히 사람만 바꾸는 게 아니다.
- 레지스터 상태 저장
- 프로그램 카운터 저장
- 다른 스레드의 상태 복원
- CPU 캐시 무효화
이 모든 과정이 실제 비즈니스 로직과는 아무 상관 없는 오버헤드다.
Redis의 작업은 워낙 짧고 빠르기 때문에,
이런 전환 비용이 실제 작업 시간보다 더 커질 수 있다.
3. 락(Lock)과 복잡도 문제
멀티 스레드를 쓰면 또 하나의 문제가 생긴다.
동시에 같은 데이터에 접근하는 문제다.
이를 해결하려면 결국 Lock을 걸어야 한다.
- Lock 획득
- 경쟁 상태 관리
- 데드락, 성능 저하 가능성
결과적으로 시스템은 더 복잡해지고,
성능은 오히려 떨어질 수 있다.
Redis는 이런 선택을 했다.
락을 관리하느니,
애초에 락이 필요 없는 구조로 가자.
그래서 싱글 스레드 + 이벤트 루프 구조를 선택했고,
이게 Redis의 단순함과 높은 성능을 동시에 만들어냈다.
4. 그런데… Redis 6.0부터 멀티 스레드를 쓰지 않나?
“어? Redis 6.0부터 멀티 스레드 지원했다는 얘기 들었는데?”
맞다.
Redis 6.0 이후에는 ‘부분적으로’ 멀티 스레드를 사용한다.
중요한 포인트는 이거다.
👉 명령 실행은 여전히 싱글 스레드다.
Redis가 멀티 스레드를 도입한 영역은
네트워크 I/O 처리 부분이다.
즉,
- 요청 읽기 (read)
- 응답 쓰기 (write)
이 부분만 여러 스레드가 처리한다.
왜냐하면 Redis의 진짜 병목이 바로 여기였기 때문이다.
- CPU 연산 ❌
- 락 관리 ❌
- 네트워크 I/O ⭕️
마무리
처음엔 그냥 “Redis 왜 싱글 스레드야?”라고 생각했는데,
알고 보니 멀티 스레드를 안 쓰는 게 아니라
쓸 이유가 없는 곳엔 쓰지 않은 것에 가까웠다.
병렬화 자체가 목적이 아니라,
병목이 생기는 지점을 정확히 보고 고친 설계라는 게 인상 깊었다.
기술을 많이 아는 것보다, 문제를 제대로 보는 게 더 중요하다는 걸 Redis가 보여주는 느낌이었다.