레디스는 기본적으로 유저 레벨에서는 싱글 스레드로 요청을 처리한다. 하지만 실제 명령에 대한 작업은 이벤트 루프를 이용해 요청을 수행하며 커널 I/O 레벨에서는 스레드 풀을 이용하여 논블로킹 방식으로 요청을 비동기 처리하고 있다.(I/O Multiplexing)
그럼 싱글 스레드로 동작하는 레디스에서 I/O Multiplexing은 어떤 요청을 처리 방식을 말하는걸까?
먼저 실행중인 레디스 프로세스를 조회해보면 아래와 같이 3개의 스레드가 동작하고 있다.

메인 스레드 외 뭔가 부가적인 작업들이 다른 스레드들에서 수행되고 있다는 것인데 레디스의 스레드를 처리하는 파일인 bio.h 를 보면 다음과 같은 코드를 볼 수 있다.
/* Background job opcodes */
enum {
BIO_CLOSE_FILE = 0, /* Deferred close(2) syscall. */
BIO_AOF_FSYNC, /* Deferred AOF fsync. */
BIO_LAZY_FREE, /* Deferred objects freeing. */
BIO_CLOSE_AOF, /* Deferred close for AOF files. */
BIO_NUM_OPS
};
보이는 것처럼 메인 스레드 외에 여러 개의 스레드를 더 호출하여 인입된 요청을 처리하고 있다.
- BIO_CLOSE_FILE
- AOF Rewrite 할 때 새 파일에 Rewrite 완료하고 기존 파일을 close 할 때 동작을 처리한다.
- BIO_AOF_FSYNC
- 1초 마다 AOF에 쓸 때 동작을 처리한다.
- BIO_LAZY_FREE
- DEL명령등의 실행 시 블로킹 현상으로 인한 장애발생을 해결하기 위해 UNLINK, FLUSHALL, FLUSHDB등의 명령이 추가되었고 이를 처리한다.
깃헙에 들어가서 코드를 뜯어보면 해당 작업들을 OS 레벨에서 비동기로 처리하기 위한 로직들이 작성되어있다.
즉, 레디스는 Multiplexing을 통해 동시성을 보장하기 때문에 실제 레디스의 데이터 작업 자체를 빠르게 해주는 것은 아니지만 싱글 스레드임에도 높은 퍼포먼스를 낼 수 있는 것이다.
+레디스 깃헙에서 각 스레드가 처리하는 로직에 대한 자세한 코드를 확인할 수 있다.
https://github.com/redis/redis/blob/unstable/src/bio.c
정리
- 동작
- 메인 스레드에서 요청 데이터 처리 (v6.0이후로는 Threaded I/O가 추가되어 멀티 스레드를 지원한다고는 한다.)
- 나머지 스레드는 요청에 대한 부가 작업 처리(I/O Multiplexing) -> 논블로킹 I/O,동시성 보장
- 싱글 스레드 장점
- context-swtich 비용을 줄일 수 있고 동기화가 필요없는 이벤트루프를 사용하기 때문에 효율적이고 확장 가능한 서버를 구축하기 좋음
ref.
'Software Engineering' 카테고리의 다른 글
사용자 인증 - Session vs Token(JWT) (1) | 2022.09.19 |
---|---|
REST API (0) | 2022.08.07 |