Redis Internal Flow Overview

레디스 내부구조 교육 레디스 정기점검/기술지원
Redis Technical Support
레디스 엔터프라이즈 서버
Redis Enterprise Server

Redis Main Flow

Redis Main Flow

Main Flow

  1. initServerConfig: 서버 구성을 위한 설정값(파라미터)를 디폴트로 넣는다. server.c
  2. loadServerConfig: redis.conf 파일에서 파리미터를 읽어서 넣는다. config.c
  3. initServer: 레디스 서버의 메인 작업으로 Time Event와 File(I/O) Event를 등록한다. 자세한 내용은 아래에 설명한다. server.c
  4. loadDataFromDisk: AOF나 RDB 파일을 읽어 데이터를 넣는다. 이때는 SET/GET같은 데이터 명령은 처리하는 않지만, INFO 같이 정보를 얻기 위한 명령은 실행할 수 있다. server.c

initServer

#define CONFIG_MIN_RESERVED_FDS 32
#define CONFIG_FDSET_INCR (CONFIG_MIN_RESERVED_FDS+96)
initServer() {
    server.el = aeCreateEventLoop(server.maxclients+CONFIG_FDSET_INCR);
    aeCreateTimeEvent(server.el, 1, serverCron, NULL, NULL)
    aeCreateFileEvent(server.el, server.ipfd[j], AE_READABLE, acceptTcpHandler,NULL)
}
  • Time Event: serverCron: 1초에 10번 실행, 10 Hz
  • File(I/O) Event: acceptTcpHandler: Client 요청 처리

serverCron

  • clientsCron: 1초에 10번 실행되며 한번 실행될 때 '클라이언트 수'/10 개수 만큼 처리한다. 따라서 모든 클라이언트가 1초에 한번을 처리된다.
    • clientsCronHandleTimeout: 클라이언트가 timeout 시간(초) 동안 아무 명령을 내리지 않으면 연결을 해제한다.
    • clientsCronResizeQueryBuffer: 클라이언트의 querybuf가 1kb 이상이면 빈 공간을 해제한다.   정확히는 (32kb 초과)이거나 (ideltime 2초 초과하고 1kb를 초과)하면 -> free가능한 space가 1kb 이상이면 sdsRemoveFreeSpace() 동작한다.
  • databasesCron:
    • activeExpireCycle: if (lazyfree_lazy_expire==yes) dbAsyncDelete() else dbSyncDelete();
    • activeDefragCycle:
    • tryResizeHashTables: Resize
    • incrementallyRehash: Rehash: 새 버킷 할당후 rehash 실행 -> Active rehashing uses 1 millisecond every 100 milliseconds of CPU time
  • rdbSaveBackground: 자식 프로세스가 rdb 파일을 만든다. save 옵션 사용 시
  • rewriteAppendOnlyFileBackground: 자식 프로세스가 AOF 파일을 다시 만든다. auto-aof-rewrite-percentage 옵션 사용 시
  • replicationCron: Reconnection과 후처리를 한다.
  • clusterCron: 레디스 서버가 클러스터 노드(cluster-enabled yes)일 때 노드간 확인 작업등을 실행한다.

acceptTcpHandler

  • createClient: 클라이언트 요청(명령)을 처리한다.

입력 명령 처리과정

  • readQueryFromClient() - aeEventLoop 입력된 명령을 c->querybuf에 저장한다.
    • processInputBufferAndReplicate(): 이 함수는 redis-5에만 있다. 다른 버전(redis-3,4,6,7)에서는 이 기능이 readQueryFromClient() 함수에 포함되어 있다. (2024년 3월 3일(일) 업데이트)
      -> 클라이언트가 마스터인지 일반인지 구분해서 처리한다.
      -> 마스터이면 복제 offset 관련해서 추가로 처리한다.
      -> processInputBuffer()를 호출한다.
      • processInputBuffer()
        -> 입력 데이터 형식(format)에 맞게 처리한다.
        -> 일반: processInlineBuffer()
        -> '*': processMultibulkBuffer() -> 복제서버가 마스터에 데이터를 받는 경우.
                  AOF도 format은 같지만 이 함수를 사용하지 않고 aof.c에서 직접 처리한다.
        -> c->argc, c->argv로 구성한 이후에 processCommand()를 호출하는 것은 동일하다.
        -> processCommand()->call()
  • processInlineBuffer() - redis-cli에서 받은 명령(문자열) 처리
    c->querybuf "set key value\n" 문자열을 받아서 '\n'으로 구분(여기까지 읽어서)
    아래와 같이 만든다.
    char *newline = strchr(c->querybuf+c->qb_pos,'\n');
    sds *argv = sdssplitargs(aux,&argc);
    c->argc = 3
    c->argv[0] = "set"
    c->argv[1] = "key"
    c->argv[2] = "value"
  • processMultibulkBuffer() - App(redis client)에서는 일반적으로 AOF 형식으로 보낸다.
    "*3\r\n$3\r\nset\r\n$3\r\nkey\r\n$5\r\nvalue\r\n"

AOF 기록, 복제 전파

Redis Client Flow
  • c->cmd->proc: 클라이언트 요청(명령)을 처리한다.
  • propagate:
    • feedAppendOnlyFile: AOF 파일에 기록하기 위해 명령을 AOF format으로 만들고 기록한다.
    • replicationFeedSlaves: 명령을 복제서버에게 보낸다.
      • feedReplicationBacklog(): 복제 백로그에 저장한다. 이것은 나중에 부분 동기화가 발생하면 사용된다.
      • addReplyBulk(): 복제노드에 명령을 바로 전달한다.

beforeSleep

  • clusterBeforeSleep: 클러스터 관련 처리
  • activeExpireCycle: Expire 관련 처리
  • replicationFeedSlaves: 복제 관련 처리
  • flushAppendOnlyFile: appendfsync가 always면 aof_fsync를 실행하고 everysec이면 aof_background_fsync를 실행한다.   자세한 내용은 AOF Internal을 참조한다.

<< MIN-REPLICAS-MAX-LAG Command Process >>

Email 답글이 올라오면 이메일로 알려드리겠습니다.