Redis 운영 관리

Redis 주요 특성

  1. Key-Value Store : 단순 스트링에 대한 key/Value 구조를 지원
  2. 컬렉션 지원 : List, Set, Sorted Set, Hash 등의 자료구조를 지원
  3. Pub/Sub 지원 : 서버간에 통지가 필요할 때 유용
  4. 디스크 저장 : 현재의 메모리 상태를 디스크에 저장 가능
  5. 복제 : 다른 노드에서 해당 내용을 복제할 수 있는 master/slave 구조 지원
  6. 빠른 속도 : 초당 50,000 ~ 60,000 QPS 이상의 처리 속도 지원

Single Thread

Redis 는 싱글 스레드이다. 그래서,
시간이 오래 걸리는 Redis 명령을 호출하면, 명령을 처리하는 동안 다른 client 의 요청을 처리할 수 없다.
이런 특성 때문에 주의해야하는 경우가 몇 가지 있다.

  1. 서버에서 keys 명령을 사용하지 마라.
    keys 명령은 서버에 저장된 key 목록을 볼 수 있는 명령이다.
    모든 key 를 대상으로 검색한다. 작업하는 동안 다른 client 의 요청을 처리할 수 없다.

  2. flushall/flushdb 명령을 주의해라.
    redis 는 db 라는 가상의 공간을 분리할 수 있는 개념이 있는데, select 명령으로 이동할 수 있다.
    그래서, 같은 key 이름이라도 db 개수에 따라 여러 개 만들 수 있다. 예를 들면,

    1
    2
    3
    4
    5
    6
    7
    select 0
    set jko "1234"
    select 1
    set jko "5678"
    get jko --> 결과 : 5678
    select 0
    get jko --> 결과 : 1234

    flushdb 는 하나의 db 를 선택해서 지우고, flushall 은 데이터 전체 내용을 지운다.
    flushall 의 경우 실제 존재하는 모든 데이터를 일일이 삭제하는데, 속도가 O(n) 이기때문에 데이터 양에 영향을 받는다.
    작업하는 동안 다른 client 의 요청을 처리할 수 없다.

Persistent : RDB/AOF

Redis 는 데이터를 디스크로 저장할 수 있는 Persistent 기능을 제공한다.
Redis 에서 제공하는 RDB 와 AOF 기능을 정리해보자.

  1. RDB
    'RDBMS' 가 아니라, 단순히 Redis 의 메모리 스냅샷을 파일로 저장한 파일 확장자이다.
    Redis 는 지속적인 서비스와 RDB 저장을 위해, fork 를 통해 자식 프로세스를 생성한다.
    이 RDB 저장을 위한 명령으로 SAVE 와 BGSAVE 가 있다.
    SAVE는, 모든 작업을 멈추고 현재 메모리 상태에 대한 RDB 파일을 생성한다.
    BGSAVE는, 자식 프로세스에서 RDB 파일을 생성한다.
  2. AOF (Append Only File)
    클라이언트가 Redis 에 업데이트 관련 명령을 요청하면, Redis 는 해당 명령을 AOF 에 저장한다.
    그리고, 실제로 해당 명령을 실행해서 메모리 내용을 변경한다.

RDB 를 저장할 때 fork 를 사용하여 문제가 되는 경우

이전에는 OS 가 자식 프로세스를 생성하면, 부모 프로세스의 메모리를 모두 자식 프로세스에 복사해야했다.
예를 들면, 부모 프로세스가 10 GB 메모리를 사용 중이라면, 자식 프로세스를 생성할 때 10 GB 메모리가 필요했다.
그런데 OS 가 발전하면서, COW (Copy On Write) 기술이 개발되었다. 그래서,
최초에 fork 로 자식 프로세스가 생성되면 부모 프로세스와 자식 프로세스는 같은 메모리를 공유한다.
그리고, 자식 프로세스에 write 가 발생할 때마다, 공유하는 해당 데이터는 자식 프로세스에 복사된다.
write 작업이 많아지면 부모 페이지에 있는 모든 페이지가 자식 프로세스에 복사되어 사용 메모리 양이 결국 두 배가 된다.

Read 는 가능한데 Write 만 실패하는 경우

Redis 기본 설정상, RDB 저장이 실패하면 해당 장비에 이상이 있다고 판단하여 write 명령을 처리하지 않고, 데이터가 변경되지 않도록 관리한다.
즉, read 가능하지만 write 가 불가능한 경우이다.
그렇다면, RDB 생성이 실패하는 경우는 언제가 있을까 ?

  1. RDB 저장할 수 있는 정도의 디스크 여유가 없는 경우
  2. 실제 디스크 고장
  3. 메모리 부족으로 자식 프로세스를 생성하지 못한 경우
  4. 강제적으로 자식 프로세스를 종료시킨 경우

Redis 복제 : master/slave

redis 복제 모델은 master/slave 구조이다. 주의할점은, 하나의 slave 는 오직 하나의 master 만 가질 수 있다.
복제 과정은 다음과 같다.

  1. slave 에서 slaveof 명령을 통해, master 서버를 설정
  2. master 는 복제를 위해 RDB 생성 후에, 슬레이브에 전송
  3. 슬레이브는 RDB 를 로드하고 나머지 차이에 대한 명령을 마스터에서 전달받아 복제 완료

master 장애시, slave 모든 내용이 사라지는 경우

  1. slave 는 master 의 상태를 지속적으로 체크한다.
  2. master 와의 연결 상태 이상을 slave 가 감지한다.
  3. slave 에서 master 와의 연결 상태가 복원된 것을 확인한다.
  4. 이제, slave 는 master 의 모든 내용을 가져온다.
  5. 그런데, 마스터에 장애가 발생해서 master 에 데이터가 하나도 없으면 slave 의 모든 내용은 사라진다.

왜 모든 내용이 사라질까 ?
왜냐하면, 슬레이브는 마스터와 동일한 데이터를 유지하기 위해 RDB 를 읽어들이기 전에 현재 자신의 데이터를 모두 삭제하고 마스터와 싱크를 맞추기 때문이다.
그래서, 마스터에 장애가 발생하면 슬레이브에 slaveof no one 명령을 줘서
더 이상 슬레이브로 동작하지 않도록 하여, 현재까지의 모든 데이터를 보존할 수 있다.

복제 시, RDB 는 무조건 백그라운드로 생성

복제를 하면, 사용자 설정과 무관하게 슬레이브에 전달할 RDB 를 만들기 위해 fork 를 해서 RDB 를 생성한다.
따라서, 하나의 프로세스가 너무 많은 메모리를 사용하지 않도록 나눌 필요가 있다.

Redis HA, Sentinel

master/slave 형태로 서비스 하기 위해서는, 다음과 같은 기능이 필요하다.

  1. 마스터 장애 판별
  2. 슬레이브를 마스터로 승격
  3. 해당 작업 내용을 클라이언트에게 통지

위와 같은 기능을 Sentinel 이라는 데몬을 이용해 처리할 수 있다.
다만, 3번 같은 경우 Sentinel 에서 이미 장애 발생한 마스터에 접속한 클라이언트를 알 수 없으므로, 해당 알림을 원하는 클라이언트는 Redis Pub/Sub 으로 Sentinel 에 등록해야한다.
즉, 마스터에 장애가 발생하면 처리 순서는 다음과 같다.

  1. Sentinel 은 슬레이브 중에 한대를 선택해서 마스터로 승격
  2. Sentinel 은 클라이언트에 Pub/Sub 으로 통지
  3. 클라이언트가 connection 을 승격된 마스터로 변경

Redis 운영 관리 <강대명>

Comments