Redis 영속성, 백업 및 복구¶
Redis 영속성 정책과 백업/복구 기준을 정리함.
1. Redis 영속성 설정¶
Redis 영속성은 데이터 유실 허용 여부에 따라 다르게 설정해야 함.
Redis의 대표적인 영속성 방식은 다음과 같음.
| 방식 | 설명 | 장점 | 단점 |
|---|---|---|---|
| RDB | 특정 시점 snapshot을 파일로 저장함 | 백업과 재시작이 단순함 | 장애 시 최근 데이터 유실 가능함 |
| AOF | write 명령을 append log로 저장함 | RDB보다 데이터 유실 가능성이 낮음 | 디스크 I/O와 파일 크기 관리가 필요함 |
| RDB + AOF | 두 방식을 함께 사용함 | 복구 안정성 향상 | 운영 복잡도와 디스크 사용량 증가 |
| persistence 미사용 | 디스크 저장을 하지 않음 | 순수 캐시 성능과 단순성 | 재시작 시 데이터가 모두 사라짐 |
1.1 순수 캐시 전용 예시¶
데이터 유실이 허용되는 캐시 전용 Redis에서는 persistence를 끌 수 있음.
save ""
appendonly no
이 설정에서는 Redis 재시작 또는 서버 장애 시 데이터가 사라짐. 세션, 결제 상태, 작업 큐, 중요 사용자 상태를 저장하는 Redis에는 사용하지 않음.
1.2 일반 운영 저장소 예시¶
세션, rate limit, 임시 상태 등 일부 데이터 보존이 필요한 경우에는 AOF everysec 또는 RDB+AOF를 검토함.
appendonly yes
appendfsync everysec
no-appendfsync-on-rewrite yes
RDB snapshot도 함께 사용할 경우:
save 900 1
save 300 10
save 60 10000
1.3 persistence 파일 위치 확인¶
Redis가 사용하는 data directory와 파일명을 확인함.
redis-cli CONFIG GET dir
redis-cli CONFIG GET dbfilename
redis-cli CONFIG GET appendonly
redis-cli CONFIG GET appendfsync
redis-cli CONFIG GET append*
일반적으로 data directory는 다음 계열 경로를 사용함.
/var/lib/redis
다만 패키지 출처와 버전에 따라 다를 수 있으므로 반드시 CONFIG GET dir로 확인함.
1.4 persistence 상태 확인¶
redis-cli INFO persistence
확인할 주요 항목:
rdb_last_bgsave_statusrdb_last_save_timerdb_last_bgsave_time_secaof_enabledaof_last_bgrewrite_statusaof_last_write_status
1.5 RDB/AOF 호환성 주의¶
Redis major/minor upgrade 또는 downgrade 시 RDB/AOF 파일 호환성을 반드시 확인함.
새 Redis 버전이 생성한 RDB 파일을 이전 Redis 버전이 읽지 못할 수 있음. 따라서 rollback 계획은 패키지 downgrade만으로 충분하지 않음.
운영 기준:
- upgrade 전 compatible backup을 생성함.
- upgrade 후 생성된 RDB/AOF를 이전 버전에서 읽을 수 있는지 가정하지 않음.
- downgrade가 필요한 경우 upgrade 전 백업 파일을 기준으로 복구함.
- 캐시 전용 Redis라면 데이터 삭제 후 재기동 가능 여부를 사전에 결정함.
- 세션/상태 저장 Redis라면 staging에서 복구 리허설을 수행함.
2. 백업 및 복구 기준¶
Redis 백업은 persistence 방식에 따라 달라짐.
운영 서버에서는 Redis를 어떤 용도로 사용하는지에 따라 백업 필요 여부를 명확히 함.
| 용도 | 백업 필요성 |
|---|---|
| 순수 캐시 | 일반적으로 백업 불필요함 |
| 세션 저장소 | 서비스 정책에 따라 검토함 |
| rate limit 저장소 | 일반적으로 백업 불필요하거나 낮은 우선순위 |
| 작업 큐 | 유실 허용 여부에 따라 백업 필요함 |
| 중요 상태 저장소 | 반드시 백업 및 복구 절차 필요함 |
2.1 RDB 백업 절차¶
RDB 파일 위치를 확인함.
redis-cli --askpass CONFIG GET dir
redis-cli --askpass CONFIG GET dbfilename
수동 snapshot을 생성함.
redis-cli --askpass BGSAVE
마지막 저장 시간을 확인함.
redis-cli --askpass LASTSAVE
redis-cli --askpass INFO persistence
수동 백업 예시:
REDIS_DIR="$(redis-cli --askpass --raw CONFIG GET dir | tail -n 1)"
REDIS_RDB="$(redis-cli --askpass --raw CONFIG GET dbfilename | tail -n 1)"
BACKUP_DIR="/backup/redis/$(date +%Y%m%d%H%M%S)"
sudo mkdir -p "$BACKUP_DIR"
sudo cp -a "${REDIS_DIR}/${REDIS_RDB}" "$BACKUP_DIR/"
sudo sha256sum "$BACKUP_DIR/$REDIS_RDB" | sudo tee "$BACKUP_DIR/$REDIS_RDB.sha256"
2.2 자동화 백업 인증 방식¶
--askpass는 대화형 입력을 요구하므로 cron, systemd timer, CI/CD 자동화에서는 적합하지 않음.
자동화 백업에서는 다음 중 하나를 사용함.
REDISCLI_AUTH환경 변수- Redis URI
- Unix socket
- secret manager 또는 root-only secret file
- systemd
EnvironmentFile
예시 secret file:
sudo install -o root -g root -m 0600 /dev/null /etc/redis/backup.env
sudo tee /etc/redis/backup.env > /dev/null <<'EOF'
REDIS_USER=ops
REDIS_PASSWORD=CHANGE_ME_TO_LONG_RANDOM_PASSWORD
EOF
sudo chmod 0600 /etc/redis/backup.env
자동화 백업 스크립트 예시:
sudo tee /usr/local/sbin/redis-rdb-backup.sh > /dev/null <<'EOF'
#!/usr/bin/env bash
set -Eeuo pipefail
ENV_FILE="/etc/redis/backup.env"
BACKUP_ROOT="/backup/redis"
BGSAVE_TIMEOUT="${BGSAVE_TIMEOUT:-60}"
if [ ! -f "$ENV_FILE" ]; then
echo "Missing env file: $ENV_FILE" >&2
exit 1
fi
# shellcheck disable=SC1090
source "$ENV_FILE"
if [ -z "${REDIS_PASSWORD:-}" ]; then
echo "REDIS_PASSWORD is not set in $ENV_FILE" >&2
exit 1
fi
export REDISCLI_AUTH="$REDIS_PASSWORD"
REDIS_USER_ARG=()
if [ -n "${REDIS_USER:-}" ]; then
REDIS_USER_ARG=(--user "$REDIS_USER")
fi
PRE_BGSAVE_STATUS="$(
redis-cli "${REDIS_USER_ARG[@]}" --raw INFO persistence \
| awk -F: '/rdb_bgsave_in_progress/ {gsub("\r","",$2); print $2}'
)"
if [ "$PRE_BGSAVE_STATUS" = "1" ]; then
echo "Another BGSAVE is already in progress. Abort this backup run to avoid copying an unrelated RDB snapshot." >&2
exit 1
fi
BGSAVE_STDERR_FILE="$(mktemp)"
BGSAVE_RESULT=""
BGSAVE_EXIT_CODE=0
if ! BGSAVE_RESULT="$(redis-cli "${REDIS_USER_ARG[@]}" BGSAVE 2>"$BGSAVE_STDERR_FILE")"; then
BGSAVE_EXIT_CODE=$?
fi
BGSAVE_STDERR="$(cat "$BGSAVE_STDERR_FILE")"
rm -f "$BGSAVE_STDERR_FILE"
if [ "$BGSAVE_EXIT_CODE" -ne 0 ]; then
echo "BGSAVE command failed with exit code ${BGSAVE_EXIT_CODE}" >&2
if [ -n "$BGSAVE_STDERR" ]; then
echo "$BGSAVE_STDERR" >&2
fi
exit 1
fi
case "$BGSAVE_RESULT" in
*"Background saving started"*|*"OK"*)
;;
*"Background save already in progress"*)
echo "Another BGSAVE is already in progress. Abort this backup run." >&2
exit 1
;;
*)
echo "Unexpected BGSAVE response: $BGSAVE_RESULT" >&2
exit 1
;;
esac
ELAPSED=0
while [ "$ELAPSED" -lt "$BGSAVE_TIMEOUT" ]; do
STATUS="$(
redis-cli "${REDIS_USER_ARG[@]}" --raw INFO persistence \
| awk -F: '/rdb_bgsave_in_progress/ {gsub("\r","",$2); print $2}'
)"
if [ "$STATUS" = "0" ]; then
break
fi
sleep 1
ELAPSED=$((ELAPSED + 1))
done
if [ "$ELAPSED" -ge "$BGSAVE_TIMEOUT" ]; then
echo "BGSAVE did not finish within ${BGSAVE_TIMEOUT}s" >&2
exit 1
fi
SAVE_STATUS="$(
redis-cli "${REDIS_USER_ARG[@]}" --raw INFO persistence \
| awk -F: '/rdb_last_bgsave_status/ {gsub("\r","",$2); print $2}'
)"
if [ "$SAVE_STATUS" != "ok" ]; then
echo "BGSAVE failed: $SAVE_STATUS" >&2
exit 1
fi
REDIS_DIR="$(redis-cli "${REDIS_USER_ARG[@]}" --raw CONFIG GET dir | tail -n 1)"
REDIS_RDB="$(redis-cli "${REDIS_USER_ARG[@]}" --raw CONFIG GET dbfilename | tail -n 1)"
if [ -z "$REDIS_DIR" ] || [ -z "$REDIS_RDB" ]; then
echo "Failed to resolve Redis RDB path" >&2
exit 1
fi
if [ ! -f "${REDIS_DIR}/${REDIS_RDB}" ]; then
echo "RDB file not found: ${REDIS_DIR}/${REDIS_RDB}" >&2
exit 1
fi
BACKUP_DIR="${BACKUP_ROOT}/$(date +%Y%m%d%H%M%S)"
mkdir -p "$BACKUP_DIR"
cp -a "${REDIS_DIR}/${REDIS_RDB}" "${BACKUP_DIR}/"
sha256sum "${BACKUP_DIR}/${REDIS_RDB}" > "${BACKUP_DIR}/${REDIS_RDB}.sha256"
unset REDISCLI_AUTH
EOF
sudo chmod 0750 /usr/local/sbin/redis-rdb-backup.sh
주의
BGSAVE는 명령 성공과 파일 저장 완료가 같은 의미가 아님.
BGSAVE명령은 background save 시작 후 즉시 반환될 수 있으므로, 자동화 백업에서는rdb_bgsave_in_progress가0이 되는지 확인하고 timeout 시 실패 처리해야 함.
timeout 없이 이전rdb_last_bgsave_status=ok만 확인하면 아직 진행 중인 백업을 성공으로 오판할 수 있음.
이미 다른BGSAVE또는 AOF rewrite가 진행 중인 경우에는 새 백업 실행을 중단하고, 이전 background save 결과를 이번 백업 결과로 오인하지 않도록 함.
자동화 스크립트에서는BGSAVE의 stdout, stderr, exit code를 구분해서 처리하는 것이 좋음. 인증 실패, 네트워크 오류, Redis 오류 응답을 같은 문자열 분기로 처리하면 원인 파악이 어려워질 수 있음.
cron 예시:
sudo tee /etc/cron.d/redis-rdb-backup > /dev/null <<'EOF'
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
15 * * * * root /usr/local/sbin/redis-rdb-backup.sh >> /var/log/redis-rdb-backup.log 2>&1
EOF
cron 로그가 무한 증가하지 않도록 logrotate 정책을 추가함.
sudo tee /etc/logrotate.d/redis-rdb-backup > /dev/null <<'EOF'
/var/log/redis-rdb-backup.log {
daily
rotate 14
missingok
notifempty
compress
delaycompress
copytruncate
create 0640 root root
}
EOF
주의
REDISCLI_AUTH도 프로세스 환경 변수 노출 가능성이 있으므로 서버 접근 권한, script 권한, env file 권한을 함께 제한함. 가능하면 secret manager 또는 systemd credential 기능을 검토함. cron으로 로그 파일에 append하는 경우 반드시 logrotate 정책을 함께 둠. systemd timer로 전환하는 경우에는 journald 보관 정책을 별도로 확인함.
2.3 AOF 백업 확인¶
AOF 사용 여부를 확인함.
redis-cli --askpass CONFIG GET appendonly
redis-cli --askpass CONFIG GET appendfilename
redis-cli --askpass CONFIG GET append*
Redis 버전에 따라 AOF 파일 구성이 단일 파일이거나 multi-part AOF 디렉터리 구조일 수 있음. 따라서 CONFIG GET append*와 data directory를 함께 확인한 뒤 백업 대상을 결정함.
2.4 복구 기본 절차¶
복구는 반드시 staging 환경에서 리허설한 절차를 사용함.
단일 Redis 서버에서 RDB를 복구하는 일반 흐름은 다음과 같음.
- 애플리케이션 write를 중지함.
- Redis 서비스를 중지함.
- 기존 data directory를 백업함.
- 복구할 RDB/AOF 파일을 data directory에 배치함.
- 파일 소유자와 권한을 Redis 사용자로 맞춤.
- Redis 서비스를 시작함.
INFO persistence, key count, 애플리케이션 기능을 확인함.
예시:
sudo systemctl stop redis
REDIS_DIR="/var/lib/redis"
RESTORE_RDB="/backup/redis/20260617000000/dump.rdb"
sudo cp -a "$REDIS_DIR" "${REDIS_DIR}.before-restore.$(date +%Y%m%d%H%M%S)"
sudo cp -a "$RESTORE_RDB" "$REDIS_DIR/dump.rdb"
sudo chown redis:redis "$REDIS_DIR/dump.rdb"
sudo chmod 0640 "$REDIS_DIR/dump.rdb"
sudo systemctl start redis
sudo systemctl status redis --no-pager
복구 후 확인:
redis-cli --askpass ping
redis-cli --askpass INFO persistence
redis-cli --askpass DBSIZE
주의 복구 절차는 Redis 버전, AOF 사용 여부, Cluster 여부, systemd unit, data directory 경로에 따라 달라질 수 있음. 운영 반영 전 반드시 staging 환경에서 복구 리허설을 수행함.