어떻게 Redis는 여러 요청을 동시에 받을까?
Techchallengearena
Redis는 주로 캐시를 위해 사용하는 애플리케이션으로, 이미 많은 분들이 실제 서비스에서 사용할 것으로 생각됩니다. 저도 이곳 저곳에서 자주 애용했는데, 문득 싱글스레드인 레디스가 요청을 실제로 어떻게 처리하는지 궁금해졌습니다.
(리눅스 기준)
1. Redis는 내부적으로 Event Loop를 사용합니다. Redis는 먼저 포트 바인딩을 위해서 리스너를 생성합니다. 이때 소켓은 Non-blocking으로 설정합니다. 이렇게 생성한 소켓의 파일 디스크립터(fd)를 epoll에 등록합니다.
2. epoll은 사용자가 추적하고 싶은 fd만 등록해서 관리해주는 기능을 제공합니다. 만약 fd 상태에 변경이 발생하면 커널이 이를 표시해주고, 사용자는 epoll_wait를 통해서 변경된 리스트만 받아올 수 있습니다.
3. Redis 서버가 시작되면 Event Loop 내에서 지속적으로 epoll_wait을 호출합니다. 만약 새로운 연결 요청이 발생하면, 처음에 바인딩한 fd 상태가 변경되기 때문에 epoll_wait 과정에서 연결 요청을 인지할 수 있습니다.
4. Redis는 accept() 함수를 통해서 새로운 소켓을 만들고, 해당 소켓의 fd를 다시 epoll에 등록합니다. 그리고 명령어 요청을 받았을 때 호출할 read handler를 등록합니다.
5. 만약 클라이언트가 생성된 커넥션으로 명령어를 보내면, epoll이 변경사항을 표시해주고, redis 메인 스레드가 이를 감지합니다. 메인 스레드는 이전에 등록한 read handler를 수행하여 데이터를 소켓 버퍼에서 애플리케이션 버퍼로 읽어들입니다. 그 후 명령어를 파싱하고, 해당 명령어를 실행합니다.
6. 메인 스레드는 명령어를 실행하고 난 후 응답을 클라이언트의 소켓 출력 버퍼에 넣습니다. 그 후, clients_pending_write 리스트에 해당 클라이언트를 추가합니다. 이후에 Event Loop가 반복되는 과정에서 해당 fd에 이벤트가 발생했음을 epoll_wait으로 감지합니다. 메인 스레드는 write 작업을 통해 클라이언트에 응답을 전달합니다.
7. 만약 io-threads 값을 1보다 크게 설정하면 threaded I/O 기능을 사용할 수 있습니다. threaded I/O 기능이 활성화되면, redis는 서버 시작 전에 미리 pthread_create 함수를 통해 IO 전용 스레드를 생성합니다.
8. 메인 스레드는 epoll_wait를 호출하기 전에 beforesleep이라는 과정을 거치는데, 이때 IO 스레드를 사용하여 밀린 I/O 작업을 처리합니다. 다만, 모든 쓰레드가 Read/Write 중 하나만 특정해서 처리할 뿐, 각 쓰레드마다 다른 작업을 수행하지 않습니다.
9. 메인 스레드는 IO 스레드가 작업을 마칠 때까지 기다립니다. Read 작업의 경우, IO 스레드는 명령어를 파싱까지 해주고 명령어를 수행하지 않습니다. IO 쓰레드가 읽기 작업을 마칠때까지 기다리던 메인 스레드가 대기하고 있다가, 명령어 수행이 밀려있는 작업을 마저 수행합니다.
서비스에서 Redis를 사용하시고 계시다면, 한번쯤 읽어보시면 좋을 것 같습니다!
P.S 블로그 구독하시면 더 많은 정보를 받아보실 수 있습니다! 😁
https://blog.techchallengearena.com/p/redis
#devops #redis #techchallengearena
다음 내용이 궁금하다면?
이미 회원이신가요?
2024년 6월 25일 오후 5:07
최
... 더 보기IT 회사의 업무에서, 지금까지는 디자이너와 특히 개발자가 병목이었는데, 대 AI 시대에는 기획자가 병목이 될 수도 있겠다. 조금이라도 규모가 있는 기업에서의 가장 큰 병목은 보통 의사결정자라는 것을 생각해보면 그렇다.
즉, 실무보다 의사결정을 AI에게 맡기는 것이 병목을 해소할 수 있는 가장 확실한 방법이며, 그러므로 부장님과 사장님을 AI로 대체하는 것이야말로 인류의 번영을 위한 가장 빠른 지름길이다. (아님. 아니 맞나?!)
쿠
... 더 보기