DB/Redis

Redis 백업과 장애 복구

Code Maestro 2023. 8. 14. 16:20
728x90

1. RDB 백업

특정 시점의 스냅샷으로 데이터를 복구한다. 재시작 시 RDB 파일이 있으면 복구한다. 


장점으로는 작은 파일 사이즈로 버전 관리를 할 수 있어서 백업 관리가 용이하고, fork를 통해 백업해서 child process서비스 중인 프로세스는 성능에 영향이 없다

 

단점으로는 틈이 있을 수 있어서 데이터 유실이 있을 수가 있고, fork를 사용해서 시간이 오래 걸려 CPU와 메모리 자원을 많이 소모한다. 그래서 데이터 무결성이나 정합성 요구가 크지 않을 때 사용한다. 

 

1.1 RDB 설정

설정 파일이 없어도 기본값으로 RDB가 활성화됐다. 설정 파일을 만들려면 템플릿을 받아 사용해야 한다.

 

저장 주기 설정(ex: 60초마다 5개 이상 변경)

save 60 5

스냅샷 저장 파일 이름

<파일이름>.dump.rdb

수동으로 스냅샷 저장

bgsave

 

1.2 Docker로 Redis 설정 파일 적용

편의를 위해 Docker를 사용하겠다. 반드시 redis 이미지를 설치해야 한다. 자세한 내용은 포스팅 참고.

 

docker run --name my-redis -d redis
docker exec -it my-redis /bin/sh

redis-cli를 실행해 준다.

 

키를 설정하고 나간다. 

중단을 하고 다시 기동해보면

그대로 있는 확인할 있다.

 

 

어딘가 복구가 됐다는 이야기인데…

 

ls 명령어로 파일을 확인해보면 Redis dump.rdb 복구를

 

 

이번에는 설정 파일을 이용해서 직접 복구를 해보자

 

https://redis.io/docs/management/config/ 링크에 들어간다.

 

다른 이름으로 링크 저장.

 

 

설정 파일을 읽어보면

 

 

스냅샷을 확인할 있다.

 

Save 통해서 저장 주기를 설정할 있다.

 

나는 60초에 10 이상의 변경이 있을 때만 저장을 있게끔 했다.

 

 

해당 디렉토리에 있는 redis.conf 파일을 마운트 해준다.

 

도커로 접속을 해보면.

 

중단을 시키고

 

다시 재시작.

 

이전과 달리 Rdb 파일이 보이지 않는다.

 

10개를 저장해보고, 다시 재시작해보면

 

Dump 있고, 저장이 됐다.

 

 

 

 

 

참고로 Bgsave 명령어를 쓰면 비동기적으로 스냅샷으로 저장을 있다.

 

실무에서 bgsave 사용을 권장한다. 이유는 스케줄 기반으로 스냅샷을 쓰다보면 예측할 없는 상황이 많이 생긴다. 예를들어 데이터가 너무 많은데 잦은 주기로 스냅샷을 하면 머신앱 서버에 부하가 걸린다. 그리고 100% 데이터 유지를 목적으로 하는 아니기에 중간중간 수동으로 bgsave 스냅샷을 사용한다.

 

 

2. AOF 백업

모든 쓰기 요청에 대한 로그를 전부 기록한다. 재시작 시 AOF에 기록된 모든 동작을 재수행하여 데이터를 복구한다. 

 

장점으로는 모든 변경사항이 기록되기에 안정적으로 데이터 백업이 가능하다. AOF 파일은 append-only 방식이라 백업 파일 손상 위험이 적다. 그리고 수행된 명령어가 저장돼서 사람이 보고 이해할 수 있고, 수정도 가능하다. 

 

단점으로는 RDB 방식보다 파일 사이즈가 커지고, RDB 방식 대비 백업&복구 속도가 느리다.

 

2.1 AOF 관련 개념

  • Log rewriting: 최종 상태를 만들기 위해 최소한의 로그만 남기려고 일부를 새로 쓴다. 
  • Multi Part AOF: Redis 7.0부터 AOF가 단일 파일에 저장되지 않고 여러 개가 사용된다.
    • base file: 마지막 rewrite 시 스냅샷 저장한다.
    • incremental file: 마지막으로 base file이 생성된 후의 변경사항이 쌓인다.
    • manifest file: 파일들을 관리하기 위해 메타 데이터를 저장한다.

 

2.2 AOF 설정

appendonly yes

AOF 사용. 기본값은 no이다

파일이름 appendonly.aof

AOF 파일이름. 

 

appendfsync everysec

fsync 정책 설정. fsync() 호출은 OS에서 데이터를 디스크에 쓰도록 설정한다. 옵션은 아래와 같다.

 

  • everysec: 1초마다 수행. 성능은 RDB 수준. 실제로 많이 사용한다. 
  • always: 새로운 커맨드가 추가될 때마다 수행. 가장 안전하지만 느리다. 너무 느려서 Redis를 사용하는 의미가 없어진다.
  • no: OS에 맡긴다. 가장 빠르지만 덜 안전하다. 커널마다 수행 시간이 다르다.

실제 디스크에서 바로 저장되는 아니라 일종의 버퍼링 시간을 가질 수가 있다.

 

2.3 Redis 파일 적용

 

이전의 redis.conf 파일을 수정.

 

Yes 바꿔주자.

 

 

설정 파일들을 마운트.

 

 

개의 값을 저장.

 

상태에서 appendonlydir 확인할 있다.

 

3개의 파일이 보인다.

 

 

실제 커멘드들을 확인할 있다.

 

 

3. Redis 복제

백업 파일만으로 장애에 있어서 미흡한 부분(백업 실패 가능성, 복구 시간)이 있다. 그래서 복제로 가용성을 향상시킬 수가 있다.

 

다른 DB도 많이 사용하는 방식. master가 죽을 때 replica 중 하나를 master로 전환하여 즉시 서비스 정상화가 가능하다. replica는 read-only 노드로 사용이 가능하여 traffic 분산 효과도 있다. 

 

3.1 복제 사용

Replica 노드에서만 설정을 통해 master-replica 복제 구성이 가능하다.

 

replicaof 127.0.0.1 6379

Replica로 동작하게 설정

 

replica-read-only

Replica는 read-only로 설정

 

유의할 점은 master 노드에는 RDB나 AOF를 이용한 백업 기능 활성화가 필수이다. (재시작 후에 비어있는 데이터 상태 복제가 되지 않도록)

 

3.2 복제 적용

 

하나의 cmd에는 master 노드 설정.

 

이전의 redis.conf 파일에

 

Master 로컬 ip 포트를 설정해준다.

 

또 다른 위의 명령어 설정

 

이러면 master 커넥팅이 된다.

 

그러면 복제가 일어나는지 확인해보자

 

또 다른 곳을  열어서

 

Master 접속하여 키를 설정하고

Replica 접속.

 

키를 조회해보면 master 데이터가 옮겨진 확인할 있다.

 

 

Master b 넣어도 slave b 들어감을 확인할 있다.

 

3.3 여러 개의 컨테이너 

위의 방식을 편하게 하기 위해 Docker-compose를 활용하여 여러 개의 컨테이너를 실행해 보자. 참고로 docker-compose란 여러 개의 컨테이너로 구성된 애플리케이션을 정의하고 실행할 수 있는 도구이다.

 

version: "3"
services:
	my-redis-a:
    	hostname: redis-master
        container_name: redis-master
        image: "bitnami/redis"
        environment:
        	- REDIS_REPLICATION_MODE = master
            - ALLOW_EMPTY_PASSWORD = yes
        ports:
        	- 6379:6379
    my-redis-b:
        hostname: redis-replicas-1
        container_name: redis-replicas-1
        image: "bitnami/redis"
        environment:
        	- REDIS_REPLICATION_MODE = slave
            - REDIS_MASTER_HOST = redis-master
            - ALLOW_EMPTY_PASSWORD = yes
        ports:
        	- 5000:6379
        depends_on:
        	- my-redis-a

 

Compose 파일을 만들고

Docker-compose 띄어보면?

 

개의 컨테이너가 동시에 뜬 걸 확인할 수 있다. 

 

4. Redis sentinel 

복제로도 부족한 부분이 있다. 바로 master 바꾸는 작업을 수동으로 해야한다해야 한다. 그걸 자동으로 해주는 Redis-Sentinel이라는 있다.

 

Redis에서 HA(고가용성)을 제공하기 위한 장치로 master-replica 구조에서 master가 다운 시에 replica를 master로 승격시키는 auto-failover를 수행한다. 

 

Sentinel은 모니터링, 알림, 자동 장애 복구, 환경 설정 제공자 기능을 제공한다. 

 

구성도는 위와 같다. Seninel 노드는 Quorum 때문에 3개 이상으로 구성됐다. 서로 연결이 안 됐고, Redis master와 replica를 모니터링한다. Client는 Sentinel을 통해 Redis에 접근한다.

 

4.1 특징

SDOWN(Subjective down)과 ODOWN(Objective down)의 2가지 판단이 있다. SDOWN은 주관적으로 sntinel 1대가 down으로 판단한다. ODOWN은 객관적으로 정족수가 충족되어 down으로 판단한다. 

 

master 노드가 down된 걸 판단하기 위해 Sentinel 노드들이 정족수(Quorum)를 충족해야 한다. 여기서 쿼럼은 각 노드로부터 투표를 받아 운영(Active) 노드를 결정하는 것을 뜻한다. 클라이언트는 Sentinel을 통해 master의 주소를 얻어내야 한다.

 

 

4.2 Sentinel 적용

편의를 위해 docker-compose를 사용했다. 

version: "3"
services:
	my-redis-a:
    	hostname: redis-master
        container_name: redis-master
        image: "bitnami/redis"
        environment:
        	- REDIS_REPLICATION_MODE = master
            - ALLOW_EMPTY_PASSWORD = yes
        ports:
        	- 5000:6379
    my-redis-b:
        hostname: redis-replicas-1
        container_name: redis-replicas-1
        image: "bitnami/redis"
        environment:
        	- REDIS_REPLICATION_MODE = slave
            - REDIS_MASTER_HOST = redis-master
            - ALLOW_EMPTY_PASSWORD = yes
        ports:
        	- 5001:6379
        depends_on:
        	- my-redis-a

    redis-sentinel-1:
        container_name: sentinel1
        image: "bitnami/redis-sentinel:latest"
        environment:
        	- REDIS_SENTINEL_DOWN_AFTER_MILLISECONDS = 3000
            - REDIS_MASTER_HOST = redis-master
            - REDIS_MASTER_PORT_NUMBER = 6379
            - REDIS_MASTER_SET = mymaster
            - REDIS_SENTINEL_QUORUM=2 
        ports:
        	- 26379:26379
        depends_on:
        	- my-redis-a
            - my-redis-b
     redis-sentinel-2:
        container_name: sentinel2
        image: "bitnami/redis-sentinel:latest"
        environment:
        	- REDIS_SENTINEL_DOWN_AFTER_MILLISECONDS = 3000
            - REDIS_MASTER_HOST = redis-master
            - REDIS_MASTER_PORT_NUMBER = 6379
            - REDIS_MASTER_SET = mymaster
            - REDIS_SENTINEL_QUORUM=2 
        ports:
        	- 26380:26379
        depends_on:
        	- my-redis-a
            - my-redis-b
     redis-sentinel-3:
        container_name: sentinel3
        image: "bitnami/redis-sentinel:latest"
        environment:
        	- REDIS_SENTINEL_DOWN_AFTER_MILLISECONDS = 3000
            - REDIS_MASTER_HOST = redis-master
            - REDIS_MASTER_PORT_NUMBER = 6379
            - REDIS_MASTER_SET = mymaster
            - REDIS_SENTINEL_QUORUM=2 
        ports:
        	- 26381:26379
        depends_on:
        	- my-redis-a
            - my-redis-b

 

실행을 해보면..

 

 

 

 

마스터를 죽였더니 Quorum 충족.

 

페일 오버 => 새로운 마스터 설정.

 

Redis-replicas-1 master 승격됐다.

 

다시 시작해보면?

 

마스터가 바뀐 확인할 있다.

 

이렇게 master 다운돼도 fail-over돼서 바꾼다.

 

 

이러면 클라이언트는 어떻게 사용할까?

 

스프링 application.yml 파일에서 모든 노드들을 적어주면 Spring-redis 라이브러리가 알아서 해준다.

 

 

출처: FastCampus 대용량 데이터 & 트래픽 처리

728x90