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 대용량 데이터 & 트래픽 처리
'DB > Redis' 카테고리의 다른 글
Redis 성능 튜닝 (0) | 2023.08.18 |
---|---|
Redis 클러스터 (0) | 2023.08.17 |
Pub/Sub 패턴으로 채팅방 구현 (0) | 2023.08.11 |
Sorted Sets으로 리더보드 구현 (0) | 2023.08.11 |
Redis로 캐시 레이어 구현 (0) | 2023.08.11 |