Redis Server Threads 쓰레드

Redis Server Course Redis Technical Support Redis Enterprise Server

레디스 서버 쓰레드

멀티 쓰레드

레디스 서버는 멀티 쓰레드입니다. 버전 3.2까지는 3개 쓰레드, 4.0부터는 4개 쓰레드가 동작합니다.   버전 3.2까지는 AOF 관련 처리만 Sub 쓰레드에서 했기 때문에 레디스가 싱글쓰레드로 알려졌고, 그렇게 생각해도 큰 무리가 없었습니다. 하지만 4.0 부터 UNLINK 명령을 Sub 쓰레드에서 처리하면서 이제는 멀티 쓰레드라고 해야 합니다.
  • 메인 쓰레드: 아래 3개의 Sub 쓰레드에서 처리하는 것 이외에 거의 모든 명령어 처리, 이벤트 처리 등을 한다.
  • Sub 쓰레드 1번(BIO_CLOSE_FILE): AOF Rewrite 할 때 새 파일에 Rewrite 완료하고 기존 파일을 close 할 때 동작한다. AOF를 활성화하지 않아도 쓰레드는 생성된다.
  • Sub 쓰레드 2번(BIO_AOF_FSYNC): 1초 마다 AOF에 쓸 때 동작한다.
  • Sub 쓰레드 3번(BIO_LAZY_FREE): UNLINK, 비동기 FLUSHALL 또는 FLUSHDB 명령을 처리할 때 동작한다. 이 쓰레드는 버전 4.0에 추가되었다.
  • 쓰레드 4번 jemalloc_bg_thd: jemalloc background thread, 버전 6.0에 추가되었다.
레디스 Sub 쓰레드 관련 소스 코드는 bio.c에 있습니다.

리눅스 명령으로 쓰레드 확인하는 방법

여기서 LWP가 Light Weight Process 즉, Thread ID입니다. NLWP는 이 프로세스의 총 쓰레드 수입니다.   첫 번째가 메인 쓰레드, 두 번째부터 네 번째까지가 Sub 쓰레드 1,2,3번입니다.
jemalloc_bg_thd 쓰레드는 ps H -o 'tid comm' pid 또는 top -H -d 1 -p pid로 확인할 수 있습니다.

strace 명령으로 쓰레드가 실행하는 system call을 확인할 수 있습니다. 이것은 2번 쓰레드가 1초 마다 한 번씩 AOF에 쓸 때 fdatasync()를 수행하는 것을 켑처한 것입니다.

멀티 쓰레드 I/O(Multi threads I/O)

  • 버전 6.0 부터 클라이언트에 대한 읽기(read)/쓰기(write)용 쓰레드를 구성할 수 있다.
  • io-threads 숫자(쓰레드 개수): 디폴트는 1이다. 1은 쓰레드를 생성하지 않고 메인 쓰레드에서 I/O를 처리하는 것으로 기존과 같다. 2 이상을 지정하면 그 만큼 쓰레드가 생성된다. 디폴트로는 생성된 쓰레드는 쓰기만 담당한다. 읽기는 메인 쓰레드에서 한다.
  • io-threads-do-reads yes/no: 디폴트 no. Yes로 설정하면 생성된 I/O용 쓰레드가 읽기/쓰기를 같이 한다. (읽기/쓰기용 쓰레드로 나뉘는 것이 아니고 한 쓰레드가 읽기/쓰기를 같이 한다.)
  • 테스트: 마스터 1대(io-threads 4)(서버 8cores) -> 복제 3대(io-threads 1)
    • src/redis-benchmark -p 6000 -t set -d 1024 -n 5000000 -q
    • Cpu4,5가 마스터, benchmark이다. si(software interrupt)가 20% 정도이다. 이는 malloc 수행에서 발생하는것으로 보인다.
    • AOF 쓰기는 쓰레드 지정과 관계없이 별도의 CPU-core를 사용한다.
      Cpu6: wa(IO wait)이 20이다.
    • 위와 같이 구성해서 테스트해보면 마스터가 CPU를 231% 사용하지만 처리 성능(초당 처리 명령수)는 오히려 5~10% 정도 떨어진다.

레디스 서버 프로세스

프로세스 2개가 동시에 실행중인 경우

리눅스의 top 명령으로 프로세스를 보고 있으면, 분명 레디스 서버는 하나만 실행중인데, 레디스 프로세스 2개가 보일때가 있습니다.   이것은 쓰레드가 아니고 레디스 프로세스 2개가 동시에 실행중인 것입니다.
레디스 서버는 RDB 파일을 저장할때와 AOF 파일을 다시 쓸 때(rewrite) 자식 프로세스를 생성해서 작업합니다.
  • RDB 파일을 저장할때
    • BGSAVE 명령을 실행해서 RDB 파일을 저장할때
    • redis.conf 파일의 save option에 의해서 RDB 파일을 저장할때
    • SLAVEOF host port 명령을 실행해서 복제하려고 RDB 파일을 저장할때
    • redis.conf 파일의 slaveof 설정으로 슬레이브 노드의 요청에 의해 RDB 파일을 저장할때
  • AOF 파일을 저장할때
    • BGREWRITEAOF 명령을 실행해서 AOF 파일을 rewrite할때 저장할때
    • redis.conf 파일의 auto-aof-rewrite-percentage 옵션에 의해서 AOF 파일을 rewrite할때 저장할때

Child Process 확인

  • Child Process가 실행 중 일 때 ps 명령으로 확인할 수 있다.
  • 구분은 CMD와 NLWP개수(1개)로 확인할 수 있다. CMD에 세 가지가 표시된다.
    • redis-aof-rewrite
    • redis-rdb-bgsave
    • redis-rdb-to-slaves: replication 용으로 RDB 파일을 생성할 때

BGSAVE 명령을 실행해서 RDB 파일을 저장할때

  • redis-cli 에서 bgsave 명령을 실행한다.
  • RDB 파일 저장 시 서버 메시지: M은 부모 프로세스이고 C는 자식 프로세스이다.   이때는 2개의 프로세스가 동시에 동작한다.   Top 명령으로 보면 redis-server 프로세스가 2개 보인다.
  • 45928:M * Background saving started by pid 61975   자식 프로세스를 생성한다
    61975:C * DB saved on disk   자식 프로세스가 RDB파일 저장 완료
    61975:C * RDB: 0 MB of memory used by copy-on-write   저장중 부모 프로세스에서 데이터 번경이 없었다
    45928:M * Background saving terminated with success

redis.conf 파일의 save option에 의해서 RDB 파일을 저장할때

  • redis.conf save 설정
  • save 900 1
    save 300 10
    save 60 10000
  • RDB 파일 저장 시 서버 메시지: 메시지는 위와 같고 시작 시 어떤 save 조건에 의해서 시작했는지가 나온다.
  • 45928:M * 10 changes in 300 seconds. Saving...

SLAVEOF host port 명령을 실행해서 복제하려고 RDB 파일을 저장할때

  • 5002번 redis-cli 에서 slaveof 127.0.0.1 5001 명령을 실행한다.
  • RDB 파일 저장 시 서버 메시지
  • 45928:M * Slave 127.0.0.1:5002 asks for synchronization
    45928:M * Full resync requested by slave 127.0.0.1:5002
    45928:M * Starting BGSAVE for SYNC with target: disk
    45928:M * Background saving started by pid 62045   자식 프로세스 시작
    62045:C * DB saved on disk
    62045:C * RDB: 0 MB of memory used by copy-on-write
    45928:M * Background saving terminated with success
    45928:M * Synchronization with slave 127.0.0.1:5002 succeeded

redis.conf 파일의 slaveof 설정으로 슬레이브 노드의 요청에 의해 RDB 파일을 저장할때

  • 슬레이브 노드가 시작할때 슬레이브 노드에서 마스터 노드에 데이터를 요청하고 마스터 노드는 RDB 파일을 만들어서 전달한다.   서버에서 나오는 메시지는 위와 같다.
  • 슬레이브 노드와 diskless 방식으로 통신을 해도 자식 프로세스가 생성되는 것은 동일한다.
    Diskless 방식은 레디스 복제를 참조하세요.

BGREWRITEAOF 명령을 실행해서 AOF 파일을 rewrite할때 저장할때

  • 자식 프로세스를 생성해서 rewrite 한다. 다음은 aof rewrite 시 나오는 서버 메시지이다.
  • 3849:M * Background append only file rewriting started by pid 3909 자식 프로세스 시작
    3849:M * AOF rewrite child asks to stop sending diffs.
    3909:C * Parent agreed to stop sending diffs. Finalizing AOF...
    3909:C * Concatenating 32.41 MB of AOF diff received from parent.
    3909:C * SYNC append only file rewrite performed
    3909:C * AOF rewrite: 47 MB of memory used by copy-on-write
    3849:M * Background AOF rewrite terminated with success
    3849:M * Residual parent diff successfully flushed to the rewritten AOF (0.00 MB)
    3849:M * Background AOF rewrite finished successfully

redis.conf 파일의 auto-aof-rewrite-percentage 옵션에 의해서 AOF 파일을 rewrite할때 저장할때

  • redis.conf 파일의 auto-aof-rewrite-percentage 옵션을 100 으로 하면 aof 파일 크기가 100%씩 늘어날때마다 aof 파일을 다시 쓴다.   이때 자식 프로세스를 생성한다.
  • 위 메시지와 동일하고 첫번째 줄에 다음 내용이 추가된다.
  • 3849:M * Starting automatic rewriting of AOF on 100% growth

<< Client Side Caching Processes & Threads >>

조회수 :

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

혹시 처음이세요?
레디스게이트에는 레디스에 대한 많은 정보가 있습니다.
레디스 소개, 명령어, SQL, 클라이언트, 서버, 센티널, 클러스터 등이 있습니다.
혹시 필요한 정보를 찾기 어려우시면 redisgate@gmail.com로 메일 주세요.
제가 찾아서 알려드리겠습니다.
 
close
IP를 기반으로 보여집니다.