DBMS/Redis

[Redis] Redis 운영 관리 정리

반응형
Redis 운영 관리를 정리한 내용입니다.


Redis의 이해


Redis의 특성

  • Key-Value 스토어
  • 컬렉션 지원
  • Pub/Sub 지원
  • 디스크 저장: Redis는 인메모리 DB이면서 memcached 등과 다르게 디스크 저장도 지원.
    • RDB: 현재 메모리의 상태를 디스크에 저장.
    • AOF: 지금까지 실행된 업데이트 관련 명령어의 집합. (set/del 등의 명령어를 기록해둠)
    • Redis에서는 가능하면 두 개를 모두 사용하는 것이 좋다지만, 디스크를 사용해서 저장하는 만큼 성능 손실은 어느 정도 감수해야 함.
  • 복제
    • Redis는 마스터/슬레이브 Replication을 지원.
    • 마스터에 장애가 발생하면 슬레이브로 서비스하거나 마스터의 부하가 많을 때에는 슬레이브를 이용해서 읽기를 처리할 수도 있음.


Redis vs Memcached

  • 속도: Redis, Memcached 모두 초당 100,000 QPS 이상의 속도
  • 자료구조: Key-Value만 지원하는 Memcached와 다르게 Redis에서는 Key-Value, List, Hash, Set, Sorted Set을 지원한다.
  • 안정성: Memcached는 장애가 거의 없는 반면에, Redis는 특성상 잘못 사용하면 프로세스 장애가 발생할 수 있음.


Redis 운영과 관리


1. Redis는 싱글 스레드다.

  • Redis는 싱글 스레드이기 때문에, 하나의 명령이 오랜 시간 소모하는 작업에는 적합하지 않다.
    • 시간이 오래 걸리는 Redis 명령을 호출하면, 명령을 처리하는 동안에는 Redis가 다른 클라이언트의 요청을 처리할 수 없기 때문
  • keys 명령 사용 금지
    • 현재 서버에 저장된 Key 목록을 볼 수 있는 keys 명령을 사용하면 장애로 이어질 가능성이 높다.
    • Key가 몇천 개 수준이라면 금방 결과가 나오지만, 몇십만 개, 몇백만 개, 몇천만 개가 넘어가면 해당 작업에 아주 많은 시간을 소모하게 되고, 작업하는 동안 다른 클라이언트의 요청은 전혀 처리되지 않아 장애가 발생할 수 있다.
  • flushall/flushdb 명령을 주의하자
    • Redis에서 모든 데이터를 삭제하는 명령인 flushall, flushdb.
      • Redis는 db라는 가상의 공간을 분리할 수 있는 개념을 제공하고 select 명령으로 이동할 수 있다. 이를 통해 같은 Key 이름이라도 db 0번, db 1번 등 db의 개수에 따라 여러 개를 만들 수 있는데
      • flushdb: 이런 db 하나의 내용을 통째로 지우는 것이 flushdb 명령
      • flushall: 모든 db의 내용을 모두 지울 수 있는 것이 flushall 명령
    • flushdb, flushall은 O(n)의 삭제 속도이므로, 데이터의 양에 영향을 받는다. Redis가 싱글 스레드이기 때문에 이런 작업을 피해야 원활한 서비스가 가능. Redis는 Memcached와 다르게 데이터를 디스크로 저장할 수 있는 Persistent 기능을 제공한다.


2. Redis Persistent

Redis는 Memcached와 다르게 데이터를 디스크로 저장할 수 있는 Persistent 기능을 제공한다.

  • Memcached의 경우 서버가 장애를 일으켜 문제가 발생하면 모든 데이터가 사라지지만, Redis는 디스크에 저장되어 있는 데이터를 기반으로 다시 복구할 수 있다.
  • 이런 Redis의 Persistent(디스크 저장) 기능이 사실 장애의 주된 원인이 된다.


2-1. RDB

  • 현재 메모리에 대한 덤프를 생성하는 기능.
  • Redis는 지속적인 서비스와 RDB 저장을 위해서 fork를 통해 자식 프로세스를 생성한다.
    • 즉 Redis가 싱글 스레드라 RDB가 만들어질 때, 아무런 요청을 못하지 않고, fork를 통해 자식 프로세스가 생성되면 현재 메모리 상태가 복제되므로, 이것을 기반으로 데이터를 저장한다.
    • 이러한 특성으로, RDB는 가장 최신의 데이터라기보다는 특정 시점의 데이터, 즉 스냅샷이라고 생각해야 한다.
  • SAVE vs BGSAVE
    • SAVE: 모든 작업을 멈추고 현재 메모리 상태에 대한 RDB 파일을 생성한다. (해당 시간 동안에는 아무런 작업을 할 수 없다)
    • BGSAVE: 자식 프로세스를 생성하는 fork 작업을 통해 자식 프로세스에서 RDB 파일을 저장한다. (백그라운드 + SAVE)


2-2. AOF (Append Only File)

  • 데이터를 저장하기 전에 AOF 파일에 현재 수행해야 할 명령을 미리 저장해 두고, 장애가 발생하면 AOF를 기반으로 복구한다.
  • 데이터 저장 순서
    1. 클라이언트가 Redis에 업데이트 관련 명령을 요청
    2. Redis는 해당 명령을 AOF에 저장
    3. 파일 쓰기가 완료되면 실제로 해당 명령을 실행해서 메모리의 내용을 변경.


3. Redis가 메모리를 두배로 사용하는 문제

  • Redis가 운영되는 중에 장애를 일으키는 가장 큰 원인RDB를 저장하는 Persistent 기능으로, fork를 사용하기 때문.
    • 이전에는 OS가 자식 프로세스를 생성하면, 부모 프로세스의 메모리를 모두 자식 프로세스에 복사해야 했다. (예를 들어 부모 프로세스가 10GB 메모리를 사용 중이라면 자식 프로세스를 생성할 때 10GB의 메모리를 추가로 필요했다.)
    • OS가 발전해 COW(Copy on Write)라는 기술이 개발되어, fork 후 자식 프로세스와 부모 프로세스의 메모리에서 실제로 변경이 발생한 부분만 차후에 복사하게 되었다.
    • 하지만 Redis와 같은 솔루션을 사용하는 곳은 대부분 Write가 많으므로 예전의 경우와 마찬가지로 메모리를 두 배로 사용하는 경우가 생긴다. (메모리가 부족해지면 문제가 발생할 수 있다)


4. Redis의 장애: Read는 가능한데 Write만 실패하는 경우

  • Redis 서버는 동작하지 않는데, 정기적인 Heartbeat (PING) 체크에는 이상이 없다고 나오는 상황이 발생할 수 있다.
    • 이러한 문제는 RDB 저장이 실패할 때, 기본 설정 상 Write 관련 명령이 동작하지 않기 때문에 발생한다. (즉 Redis 기본 설정상 RDB 저장이 실패하면 Write 명령을 더는 처리하지 않으며, 데이터가 변경되지 않도록 관리한다)
  • RDB 생성에 실패하는 경우
    • RDB를 저장할 수 있을 정도의 디스크 여유 공간이 없는 경우
    • 실제 디스크가 고장 난 경우
    • 메모리 부족으로 자식 프로세스를 생성하지 못한 경우
    • 강제적으로 자식 프로세스를 종료시킨 경우 외 기타
    이러한 이유 등으로 RDB 저장이 실패하면 Redis 내부의 'lastbgsave_status' 라는 변수가 REDIS_ERR로 설정된다. 이렇게 되면 Write 관련 요청은 모두 무시하게 된다.


Redis 복제


Redis 복제 모델

  • Redis는 마스터/슬레이브 형태의 복제 모델을 제공하며, 이를 통해 마스터의 변경이 슬레이브로 전파된다.
  • slaveof라는 명령을 통해 다른 장비를 현재 장비의 마스터로 설정할 수 있다.


Redis 복제 과정

  • 슬레이브에서 slaveof 명령을 이용해 마스터 서버를 설정한다.
  • 마스터 서버가 설정되면, replicationCron에서 현재 상태에 따라 connectWithMaster를 호출한다.
  • 마스터는 복제를 위해 RDB를 생성한 후 슬레이브에 전송한다.
  • 슬레이브는 RDB를 로드하고, 나머지 차이에 대한 명령을 마스터에서 전달받아 복제를 완료한다.


Redis 복제 시 주의사항

  • slaveof no one을 기억하자
    • 슬레이브는 마스터의 상태를 지속적으로 감시하면서 바뀌는 내용을 계속 전달 받는다.
      • 이때 만약 이상이 발생해서 마스터와 연결이 끊어지면 재접속을 시도하며, 마스터에서 전체 데이터를 다시 가져와 마스터의 최종 상태로 자신의 데이터를 변경한다.
    과정
    1. 슬레이브는 마스터의 상태를 지속적으로 체크한다.
    2. 마스터와의 연결 상태상 이상을 슬레이브가 감지한다. (마스터의 장애일 수도 있고, 네트워크 사정으로 인해 슬레이브가 마스터에 제대로 연결되지 못할 수도 있다)
    3. 슬레이브에서 마스터와의 연결 상태가 복원된 것을 확인. (이 과정에서 다시 마스터의 모든 내용을 가져온다)
    4. 다만 마스터에 장애가 발생하여 마스터에 데이터가 하나도 없는 경우에는 슬레이브의 모든 내용이 사라진다.
  • 이 문제는 가장 마지막에 emptyDb를 호출하기 때문에 발생한다. (마스터와 동일한 데이터를 유지하기 위해서 RDB를 읽어들이기 전에 현재 슬레이브의 데이터를 모두 삭제하고 마스터와 싱크를 맞추므로, 마스터에 데이터가 없을 경우 모든 데이터가 날라간다.)
    • 이 경우 장애 발생 시 슬레이브를 사용할 수 없게 된다.
  • 명시적으로 현재 마스터에 장애가 일어난 것을 알고 있다면, 해당 슬레이브에 slaveof no one 명령을 줘서 더 이상 슬레이브로 동작하지 않도록 설정한다.
    • slaveof no one 명령을 주면 현재까지의 데이터를 모두 보존하기 때문에 데이터의 유실이 없다.
  • 복제 시에 무조건 RDB를 백그라운드로 생성한다는 것을 주의.
    • 일반적으로 RDB를 사용하면 메모리를 두 배로 사용할 가능성이 있기 때문에 RDB를 사용하지 않는 경우도 있다.
    • 반면 복제를 하면, 사용자의 설정과 무관하게 무조건 슬레이브에 전달할 RDB를 만들기 위해 fork를 해서 RDB를 생성한다.
    • 따라서 하나의 프로세스가 너무 많은 메모리를 사용하지 않도록 나누는 과정이 필요.
반응형

'DBMS > Redis' 카테고리의 다른 글

Redis에서 트랜잭션 처리 방법  (0) 2022.12.22
[Redis] Redis 세미나 정리  (0) 2021.09.15