특정 시간에 Shell Crontab을 이용한 Redis RDB 방식으로 백업

Mugeon Kim·2023년 11월 10일
0

서론


  • CStudy 프로젝트를 진행을 하면서 Redis를 사용을 하였습니다. 로컬 캐시를 사용하지 않은 이유는 다양한 자료구조, 분산처리의 유용하다고 생각하여 선택을 하였습니다.
  • Redis에는 캐싱, 회원의 점수, 문제에 대한 정보를 저장하기 때문에 데이터의 정합성이 중요합니다.
  • 최근에 프로젝트를 배포하고 운영을 하면서 DB 서버 오류가 발생하여 Redis 데이터의 발생하였습니다.
  • 이러한 문제를 해결하기 위하여 Redis의 데이터를 백업을 하며 학습한 내용을 정리했습니다.

본론


Redis 백업

  • Redis 백업 방식을 살펴보면 RDB (snapshotting) 방식과 AOF (Append only file) 두가지가 있다.
  • 이때 이 두가지 방식에는 차이가 있습니다.
  1. RDB방식은 특정한 각격마다 메모리에 있는 레디스 데이터 전체를 디스크에 쓰는 것이다. 이를 통하여 백업에 이점을 가져갈 수 있다.

  2. AOF 방식은 명령이 실행될때 마다 데이터를 파일에 기록하여 데이터 손실이 거의 없다.

Redis RDB 방식

  • RDB 방식은 특정 시점의 스냅샷으로 데이터를 저장한다. 재시작 시 RDB 파일이 있으면 읽어서 복구한다.

  • 장점

  1. 작은 파일 사이즈로 백업 파일 관리가 용이하다. ( 원격지 백업, 버전 관리 )
  2. Fork를 이용해 백업하므로 서비스 중인 프로세스에 성능에 영향이 없다.
  3. 데이터 스냅샷 방식이므로 빠른 복구가 가능하다.
  • 단점
  1. 스냅샷을 저장하는 시점 사이의 데이터 변경사항은 유실될 수 있다.
  2. fork를 이용하기 때문에 시간이 오래 걸릴 수 있고, CPU와 메모리 자원을 많이 소모한다.
  3. 데이터 무결성이나 정합성에 대한 요구가 크지 않은 경우 사용 가능하다. ( 마지막 백업 시 에러 발생의 문제 )
  • .rdb 파일은 AOF 파일보다 사이즈가 작다는 특징이 있다. 따라서 로딩 속도가 AOF보다 빠르다.

RDB 방식의 저장 - Save, bgsave 방식

  • 방식에는 크게 2가지가 있다.

1번 Save 방식

  • 싱글 스레드로 작업을 수행을 합니다. 작업이 완ㄹ되기 까지 모든 요청이 대기하게된다.

2번 bgsave 방식

  • 멀티 스레드 형식으로 비동기로 작업을 수행한다. redis 서비스에서 사용중인 데이터는 모두 메모리에 있는데 작업을 수행한다. 서비스 영향 없이 스냅샷으로 저장하기 위해서는 Copy-on-Write(COW) 방식을 사용한다.

  • 자식 프로세스 fork 후 부모 프로세스의 메모리에서 실제로 변경이 발생한 부분만 복사한다. wrtie 작업이 많아서 부모 페이지 전부에 변경이 발생하게 되면 부모 페이지 전부를 복사하게 된다.

  • 이때 자원을 많이 사용하기 때문에 cpu, memory를 체크를 해야된다. 나는 새벽 2시에 작업을 수행하게 하여 이 문제를 우회를 하였다.

  • 일단 docker의 redis의 데이터를 백업하기 위하여 .sh를 작성을 하였습니다.
#!/bin/bash

# 사용자 프로파일 로드
. ~user1/.bash_profile

# Redis CLI를 사용하여 백그라운드에서 스냅샷 생성
docker exec study-redis redis-cli BGSAVE

# 백그라운드 세이브 작업이 완료될 때까지 대기
sleep 10

# 현재 시간을 이용하여 백업 파일명 생성
backup_filename="dump_$(date +"%Y%m%d%H%M%S").rdb"

# 생성된 스냅샷 파일을 호스트의 안전한 위치로 복사
docker cp study-redis:/data/dump.rdb "/home/ubuntu/CStudy_Infra/$backup_filename"
  • 여기서 ~user1/.bash_profile에 대한 궁금증이 생길 수 있다. 이 부분은 Cronntab을 위해 작성을 하였다. 이 부분 때문에 2시간을 삽질을 했다.이 부분은 Crontab과 관련이 있어 밑에서 설명을 하겠습니다.

Redis AoF 방식


모든 쓰기 요청에 대한 로그를 저장
재시작 시 AOF에 기록된 모든 동작을 재수행해서 데이터를 복구

장점
1. 모든 변경사항이 기록되므로 RDB 방식 대비 안정적으로 데이터 백업 가능
2. AOF 파일은 append-only 방식이므로 백업 파일이 손상될 위험이 적음
3. 실제 수행된 명령어가 저장되어 있으므로 사람이 보고 이해할 수 있고 수정 가능

  • 만약 flushAll 같은 명령어가 잘못 입력되어도 파일에서 수정이 가능

단점
1. RDB방식보다 파일 사이즈가 크다.
2. RDB 방식 대비 백업&속도가 느리다. (백업 성능은 FSYNC 정책에 따라서 조절이 가능하다.)

AOF 자세항 이야기

  • AOF에 대해서 자세하게 적기보다는 자세하게 나온 사이트를 통해서 알 수 있다.

RDB 방식을 선택한 이유

  • 데이터의 정합성을 위해서는 AOF 방식이 좋고 많은 사람들이 선호한다. 하지만 내가 RDB 방식을 처리한 이유는 일단 파일의 크기이다. 최근 EC2로 Auto scailing을 학습하면서 aws 비용이 많이 나와 이번 db ec2는 micro로 설정을 하였습니다. 또한 메모리, cpu의 사용량이 많은 rdb방식과 백업하는 순간 데이터의 유실이 있을 수 있는 단점을 해결하기 위하여 Shell, Crontab을 이용하여 새벽 2시에 작업을 수행하면 이 문제에 대해서 해결할 수 있다고 생각했습니다.

Crontab

CRON

  • 유닉스 계열 운영체제의 JOB 스케줄러로 날짜, 시간 조건에 따라 주기적으로 특정 로직을 실행하는 프로그램입니다.

  • Crontab은 Cron 설정 정보를 파일로 관리하는 기능입니다.

  • Cron과 Crontab 모두 크게 용어를 구분하지 않고 스케줄러라는 의미로 사용을 한다.

표현식

  • Cron 표현식은 총 7자리를 사용을 합니다. 왼쪽부터 초, 분, 시간, 일, 월, 요일, 연을 의미합니다.

Spring 프레임워크에서는 스케줄러 라이브러리를 사용할 때, 연을 제외한 6자리를 사용한다.
Crontab에서는 초와 연을 제외한 5자리를 사용한다.

Shell, 쉘 스크립트

  • Shell : 사용자가 입력한 명령어를 해석하고 프로그램을 실행시키는 인터페이스

  • 쉘 스크립트 : 쉘로 작성한 명령어를 스크립트로 작성해, 한 줄 씩 실행하도록 만든것이다.

실제로 백업하기

  • 일단 crontab을 설치를 해야됩니다.
# cron 설치
sudo apt update -y
sudo apt install -y cron
# cron 시작
sudo service cron start
# cron systemctl 활성화
sudo systemctl enable cron.service
# cron systemctl 등록 확인
sudo systemctl list-unit-files | grep cron
sudo service cron status
  • 이후 쉘 스크립트를 하나 작성을 하겠습니다.

  • 만약에 없다면 vi redis_backup_script.sh을 입력하셔서 만드시면 되지만 저는 Github Repo에 Infra에 관련된 파일이 있어서 Clone을 했습니다.

  • cat redis_backup_script.sh을 통해 내용을 살펴보겠습니다.

#!/bin/bash

# 사용자 프로파일 로드
. ~user1/.bash_profile

# Redis CLI를 사용하여 백그라운드에서 스냅샷 생성
docker exec study-redis redis-cli BGSAVE

# 백그라운드 세이브 작업이 완료될 때까지 대기
sleep 10

# 현재 시간을 이용하여 백업 파일명 생성
backup_filename="dump_$(date +"%Y%m%d%H%M%S").rdb"

# 생성된 스냅샷 파일을 호스트의 안전한 위치로 복사
docker cp study-redis:/data/dump.rdb "/home/ubuntu/CStudy_Infra/$backup_filename"
  • 여기서 bgsave를 통하여 redis의 데이터를 백업을 하고 시간에 따라 파일을 저장을 하게 만들었습니다.
  • 여기서 user/.bash_profile을 작성하지 않으면 아마도 crontab으로 일정 주기에 따라 실행이 되지 않습니다.

실행이 되지 않는 이유

  1. Crond 데몬은 .sh 파일을 찾지 못합니다.
  • cron 데몬은 root 계정이 실행했으며 root계정의 shell 환경이고 .sh는 user1계정에서 만들어졌으며 user1계정은 shell 환경입니다.
  • 리눅스에서 shell 환경에서 다른 파일을 찾을 수 없습니다. Path를 잡아주면 되지만 공통 영역까지 제어하게 되면 shell을 최대한 활용하기 힘듭니다.
  1. .sh 수행할 때 user1계정에만 종속된 변수나 라이브러리를 사용
  • 리눅스 계정이 다른 shell 환경의 변수나 라이브러리를 알 수 없습니다.
  • crond은 .sh 실행중에 user1계정의 변수나 라이브러리에서 오류가 발생하며 종류합니다.

Cron 설정하기

  • cron을 설치를 하였기 때문에 crontab -e를 통하여 조건을 작성을 하겠습니다.
  • 저는 새벽 2시에 sh를 실행하고 관련 로그를 찍게 작성을 하였습니다.
  • 여기서 저장하는 방식이 조금 다른데 컨트롤 +x를 누르고 Y엔터를 눌러서 저장을 합니다.

  • 그러면 잘 적용이 되었는지 확인을 하겠습니다. crontab -l을 통해 조회를 할 수 있습니다.

  • 이후 저는 테스트를 위하여 3분마다 저장을 하게 만들었더니 성공적으로 rdb 파일이 만들어졌습니다.

  • 만약에 crontab이 작성을 했지만 정상적으로 동작을 하지 않는다면 cat /var/log/syslog | grep CRON을 통하여 확인할 수 있습니다.


결론


  • 물론 AOF 방식이 데이터의 정합성으로 좋은 방식이라고 생각하지만 현재 프로젝트의 상황과 제한된 리소스에서 RDB 방식이 더 적합하고 문제점을 Shell, Cron을 통하여 해결할 수 있다고 생각을 하였습니다.

  • 물론 이 방식이 나중에 사람들이 많이 사용을 한다면 변경이 필요하지만 그때는 현재 방식의 문제점을 더 개선하는 redis sentinel을 통하여 해결을 하고 싶다.

  • 리눅스에 대해서 명령어만 알고 있었는데 직접 shell, cron을 설정 및 작성을 하였는데 더욱 학습이 필요하다고 생각이 들었다.

참고

https://sidepower.tistory.com/17

https://inpa.tistory.com/entry/REDIS-%F0%9F%93%9A-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%98%81%EA%B5%AC-%EC%A0%80%EC%9E%A5%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95-%EB%8D%B0%EC%9D%B4%ED%84%B0%EC%9D%98-%EC%98%81%EC%86%8D%EC%84%B1

https://ourcstory.tistory.com/63

https://cloud-allstudy.tistory.com/104

https://jdm.kr/blog/2

profile
빠르게 실패하고 자세하게 학습하기

0개의 댓글