반응형
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 기능을 제공한다.
- Redis에서 모든 데이터를 삭제하는 명령인 flushall, flushdb.
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를 기반으로 복구한다.
- 데이터 저장 순서
- 클라이언트가 Redis에 업데이트 관련 명령을 요청
- Redis는 해당 명령을 AOF에 저장
- 파일 쓰기가 완료되면 실제로 해당 명령을 실행해서 메모리의 내용을 변경.
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를 저장할 수 있을 정도의 디스크 여유 공간이 없는 경우
- 실제 디스크가 고장 난 경우
- 메모리 부족으로 자식 프로세스를 생성하지 못한 경우
- 강제적으로 자식 프로세스를 종료시킨 경우 외 기타
Redis 복제
Redis 복제 모델
- Redis는 마스터/슬레이브 형태의 복제 모델을 제공하며, 이를 통해 마스터의 변경이 슬레이브로 전파된다.
- slaveof라는 명령을 통해 다른 장비를 현재 장비의 마스터로 설정할 수 있다.
Redis 복제 과정
- 슬레이브에서 slaveof 명령을 이용해 마스터 서버를 설정한다.
- 마스터 서버가 설정되면, replicationCron에서 현재 상태에 따라 connectWithMaster를 호출한다.
- 마스터는 복제를 위해 RDB를 생성한 후 슬레이브에 전송한다.
- 슬레이브는 RDB를 로드하고, 나머지 차이에 대한 명령을 마스터에서 전달받아 복제를 완료한다.
Redis 복제 시 주의사항
- slaveof no one을 기억하자
- 슬레이브는 마스터의 상태를 지속적으로 감시하면서 바뀌는 내용을 계속 전달 받는다.
- 이때 만약 이상이 발생해서 마스터와 연결이 끊어지면 재접속을 시도하며, 마스터에서 전체 데이터를 다시 가져와 마스터의 최종 상태로 자신의 데이터를 변경한다.
- 슬레이브는 마스터의 상태를 지속적으로 체크한다.
- 마스터와의 연결 상태상 이상을 슬레이브가 감지한다. (마스터의 장애일 수도 있고, 네트워크 사정으로 인해 슬레이브가 마스터에 제대로 연결되지 못할 수도 있다)
- 슬레이브에서 마스터와의 연결 상태가 복원된 것을 확인. (이 과정에서 다시 마스터의 모든 내용을 가져온다)
- 다만 마스터에 장애가 발생하여 마스터에 데이터가 하나도 없는 경우에는 슬레이브의 모든 내용이 사라진다.
- 슬레이브는 마스터의 상태를 지속적으로 감시하면서 바뀌는 내용을 계속 전달 받는다.
- 이 문제는 가장 마지막에 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 |