📌Redis의 백업
In-memory DB
- Redis는 In-memory 데이터 저장소이므로 서버를 재시작하면 모든 데이터가 사라진다.
- Redis를 캐시 이외에도 용도로 사용할 경우, 데이터를 미리 백업해 두어야 한다.
Redis Persistence
- 메모리의 데이터를 디스크에 저장하여 영속화하는 기능
- 방식
- RDB (Redis Database) : 주기적으로 특정 시점의 스냅샷을 남기는 방식
- AOF (Append Only File) : 모든 쓰기 명령에 대한 로그를 남기는 방식
📌RDB : 주기적으로 특정 시점의 스냅샷을 남기는 방식
특징
- 특정 시점의 데이터 전체를 바이너리 파일로 저장한다.
- 기본적으로 dump.rdb 파일에 저장된다.
장점
- 비교적 파일 사이즈가 작다.
- 대량의 데이터를 빠르게 로드할 수 있다.
- AOF 가 10초 걸린다면, RDB는 7초 정도로 생각하면 된다.
bgsave
를 활용하면, fork()로 자식 프로세스를 이용해 디스크에 영속화할 수 있다.
- 메인 프로세스는 디스크 I/O를 하지 않고, 클라이언트의 요청을 계속 처리할 수 있다.
단점
- 갑자기 Redis가 중지되는 경우, 가장 최근 스냅샷 이후의 데이터가 손실된다.
save
를 활용하면, 데이터가 너무 큰 경우에 fork()에 소요되는 시간이 길어져서 클라이언트의 요청을 처리하지 못하는 상황이 발생한다.
save, bgsave
save 900 1
bgsave 900 1
$ config get save
$ config get bgsave
$ config set save 900 1
$ config set bgsave 900 1
- 둘 다 RDB 파일을 생성하는 설정이다.
save
: 파일 쓰기 작업을 메인 프로세스가 직접 하기 때문에, 작업이 종료될 때까지 클라이언트의 명령을 처리할 수 없다.
bgsave
: 파일 쓰기 작업을 자식 프로세스에서 수행하기 때문에, 작업 중에도 클라이언트의 명령을 처리할 수 있다.
- save 동작
- 메인 프로세스가 데이터를 임시 RDB 파일에 쓴다.
- 쓰기가 끝나면 현재 RDB 파일을 삭제하고, 임시 RDB 파일로 교체한다.
- bgsave 동작
- 자식 프로세스를 fork() 한다.
- 자식 프로세스는 데이터를 임시 RDB 파일에 쓴다.
- 그 동안에 메인 프로세스는 클라이언트의 요청을 처리할 수 있다.
- 쓰기가 끝나면 현재 RDB 파일을 삭제하고, 임시 RDB 파일로 교체한다.
📌AOF : 모든 쓰기 명령에 대한 로그를 남기는 방식
특징
- AOF파일은 Redis에서 발생한 모든 데이터의 변경 이력을 저장한다.
- 입력/수정/삭제 명령이 실행될 때마다 AOF 파일에 명령과 데이터를 기록한다.
- AOF 파일을 rewrite하여 데이터를 복원할 수 있다.
장점
단점
- AOF에 데이터가 계속 추가되기 때문에 파일 사이즈가 커진다.
- 사이즈가 크기 때문에 서버 시작시 로딩 속도가 느리다.
- 이 경우, rewrite를 통해 파일 데이터를 다시 써서 사이즈를 줄인다.
rewrite
- AOF 파일은 text 파일이므로 수정 가능하다.
- rewrite를 통해 불필요한 데이터를 제거하여 파일 사이즈를 줄인다.
- ex)
set
명령으로 동일한 key의 value를 5번 변경하면 메모리에는 수행된 값만 남아있다. 하지만 AOF에는 5번이 모두 남아있기에, 이전 기록은 모두 지우고 최종 데이터만 기록하여 파일 사이즈를 줄일 수 있다.
- ex) 실수로
flushall
명령을 수행한 경우, 서버를 종료한 후, AOF파일을 열어서 flushall 명령을 삭제하고 재시작하면 된다.
- 동작 순서
- 자식 프로세스가 fork()를 수행한다.
- 자식 프로세스는 기존 데이터를 새로운 임시 AOF 파일에 쓴다.
- 동시에, 메인 프로세스는 새로운 명령을 처리하면서, 현재 AOF 파일에 쓴다.
- rewrite 작업이 실패해도 데이터를 안전하게 보존하기 위함이다.
- rewrite 작업 실패 시 데이터 보존을 위해..
- 자식 프로세스가 fork()된 시점의 데이터 쓰기가 완료 되면 메인 프로세스에게 stop 시그널을 보낸다. (1차 쓰기)
- 메인 프로세스가 stop 시그널을 받으면, 1차 쓰기 동안 추가로 발생한 데이터를 자식 프로세스에게 전송한다.
- 자식 프로세스는 해당 데이터를 받아 임시 AOF파일에 쓰고, 완료되면 메인 프로세스에게 완료 시그널을 보낸다. (2차 쓰기)
- 메인 프로세스는 임시 AOF 파일을 열고, 2차 쓰기 동안 추가로 발생한 데이터를 쓴다. (3차 쓰기)
- 3차 쓰기가 완료되면 현재 AOF 파일을 삭제하고, 임시 AOF 파일로 교체한다.
📌 복구
redis.conf의 appendonly
- 별도의 명령 없이, Redis를 재시작할 때 appendonly 속성에 따라 복구가 이루어진다.
- appendonly 설정이 yes인 경우, AOF 파일을 먼저 읽는다.
- AOF 파일이 없다면 RDB 파일이 있어도 읽지 않는다.
- appendonly 설정이 no인 경우, RDB 파일을 먼저 읽는다.
- RDB 파일이 없다면, AOF 파일이 있어도 읽지 않는다.
AOF를 ‘기본’으로 하고, RDB를 ‘옵션’으로
- AOF는 최근의 데이터까지 복구할 수 있다.
- AOF를 사용해도 성능에 성능에 거의 영향을 미치지 않는다.
- AOF 시간 설정은 매초 fsync로 하고, AOF Rewrite를 사용한다.
- 빠른 재시작을 위해 데이터베이스 백업으로 RDB 스냅샷을 저장하여 바로 복구하는 방식을 추가로 사용할 수 있다.
RDB를 ‘기본’으로 하고, AOF를 ‘옵션’으로
- 장애가 났을 때, 데이터 유실이 생겨도 괜찮은 경우에 사용한다.
- 최근의 데이터가 유실될 가능성이 있다.
📌 실습
AOF를 적용하기 위해, redis.conf의 appendonly 속성을 yes로 설정하였다.
나머지 속성들은 기본값을 사용하였다.
변경 사항을 저장하고, Redis를 재시작한다.
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble yes
...
GASOMANN의 경우, Redis의 Sorted Set 자료구조를 이용해 랭킹 시스템을 구축하였다.
테스트를 위해 dev-server에 더미데이터를 생성하는 API를 추가하였는데, 이것을 호출하면 Redis-server에 랭킹 데이터가 저장된다.
아래는 API를 호출한 결과이다.
앞서 AOF를 적용하였기 때문에, 모든 쓰기 동작이 appendonly.aof에 기록되어 있다.
따라서, Redis를 재시작해도 데이터가 그대로 있는 것을 확인할 수 있다.
📌Redis 환경 설정
설정 방법
- redis.conf 파일 변경
- 실시간 명령 (
config set
)
- Redis가 운영되는 중에만 적용된다.
- 영구 적용을 위해서는 redis.conf 파일을 변경해야 한다.
config rewrite
명령으로 현재의 설정을 redis.conf 파일에 저장할 수 있다.
redis.conf 주요 설정
- 기본 설정
port
: 인스턴스가 사용할 서비스 포트 (default : 6379)
bind
: 인스턴스가 사용할 네트워크 설정. 사용할 아이피 설정. bind 192.168.10.100
timeout
: 연결된 클라이언트의 유휴 대기 시간
- 해당 시간동안 송/수신이 발생하지 않으면 클라이언트의 연결을 끊는다.
- 0으로 설정하면 사용하지 않을 수 있다.
loglevel
: 인스턴스 동작 중에 출력되는 로그의 레벨을 지정
logfile
: 로그가 저장되는 경로와 파일명을 지정
database
: 레디스에서 제공하는 논리적으로 분리된 데이터 저장공간
- RDBMS의 스키마 개념과 동일하다.
- 각각의 데이터베이스는 숫자로 구분된다.
- 기본값으로 16이 사용되며, 16개의 분리된 데이터 저장 공간을 사용한다.
- 레디스에 연결된 클라이언트는 기본적으로 database 0에 접속하게 된다.
- 0번 이외의 데이터베이스에 접속 시 명령창에 [index] 가 출력되어 접속 중인 데이터베이스를 확인 할 수 있다.
- 백업 - RDB (스냅샷)
save
: 스냅샷을 찍는 주기를 설정한다.
- 시간/키 변경회수의 쌍으로 설정한다.
- save 300 10 : 300초 경과 혹은 키 변경이 10개 발생 시 스냅샷
- save 900 1 : 900초 경과 혹은 키 변경이 1개 발생 시 스냅샷
- save 설정이 여러 개인 경우, 하나라도 만족하면 스냅샷이 작동한다.
- save “” 로 설정하면 스냅샷을 사용하지 않는다.
stop-writes-on-bgsave-error
: 스냅샷에 의해 dump.rdb에 내용을 저장하는 도중쓰기 오류가 발생할 경우 행동을 설정한다. save에만 해당하고, bgsave에는 해당하지 않는다.
- no : 쓰기 요청에 실패해도, 에러 없이 이후 동작을 정상 처리한다.
- 서비스를 계속 유지하는 것이 중요할 경우 권장된다.
- yes : 쓰기 오류가 발생하는 것을 감지하고, 모든 쓰기 요청을 거부한다.
rdbcompression
: 스냅샷 파일을 저장할때 파일의 압축 여부를 설정.
- 압축 시, dump.rdb 파일의 크기는 줄어 들지만, 작업할 때 CPU 사용률이 높아진다.
- 압축률이 그다지 높지 않아 보통은 사용하지 않는다.
dir
: 레디스의 작업 디렉토리를 지정한다.
- 레디스가 생성하는 파일의 기본 위치로 사용된다.
- dump.rdb, aof 파일, 로그파일 등이 저장된다.
dbfilename
: 스냅샷 파일의 이름을 설정한다. (default : dump.rdb)
- 백업 - AOF
appendonly
: AOF 기능의 사용 여부를 설정한다. (default : no)
- on : AOF 파일을 읽는다.
- off : RDB 파일을 읽는다.
appendfilename
: AOF 파일명을 지정한다. (default : appendonly.aof)
- 해당 위치에 파일이 없거나 생성에 실패하면 오류 메세지를 출력하고 종료한다.
appendfsync
: 데이터를 dump.rdb 또는 AOF 파일에 쓸 때, fsync() 함수를 호출해 버퍼의 내용을 디스크에 즉시 기록할지 여부를 결정한다.
- 데이터가 유실될 위험은 줄어들지만, 파일 기록 성능이 저하 될 수 있다.
- no : fsync() 함수를 호출 하지 않는다.
- OS로 쓰기 명령을 전달하고, OS에서 알아서 파일에 저장하도록 한다.
- 빠른 성능을 제공하지만 , OS에 쓰기 명령을 전달하고 완료되기 전에에 문제가 생기면 데이터 손실이 발생할 수 있다.
- always : 각 명령어를 AOF 파일에 기록하고 나서 항상 fsync()함수를 호출한다.
- 느린 성능을 제공하지만 안전하게 데이터를 저장할 수 있다.
- everysec : 매 초마다 fsync() 함수를 호출한다. (default)
no-appendfsync-on-rewrite
: appendfsync 값이 always나 everysec으로 되어 있을 경우, 대량의 AOF 또는 스냅샷을 쓸 때 디스크의 성능에 따라 성능 이슈가 발생 할 수 있다. 이 때, fsync() 함수 호출을 하지 않도록 할 수 있다.
- no : 기존대로 fsync()를 호출한다.
- yes : fsync()를 사용하지 않는다.
- 이럴 경우 fsync() 함수 호출을 하지 않게 한다. NO로 설정하면 기존대로 fsync()함수를 호출하고, YES로 설정해야 fsync()를 사용하지 않는다.
auto-aof-rewrite-percentage
: AOF 파일 사이즈가 특정 퍼센트 이상 커지면 rewrite하는 설정 (default : 100)
- 레디스 서버가 시작할 시점의 AOF 파일 사이즈를 기준으로 퍼센트를 측정한다.
auto-aof-rewrite-min-size
: AOF 파일 사이즈가 특정 사이즈 이하면 rewrite를 하지 않도록 하는 설정
- 파일 크기가 작을 때,
auto-aof-rewrite-percentage
에 의해 rewrite가 자주 발생하는 것을 막아준다.
- 제한 설정
maxclient
: 인스턴스에 접속 할 수 있는 최대 클라이언트 수를 지정한다. (default : 1024)
- OS의 ulimit 값과도 연관이 있기 때문에 ulimit 제한도 함께 변경해야 한다.
- /etc/limits.conf , /etc/security/limits.conf
maxmemory
: 인스턴스가 데이터 저장에 사용할 메모리 크기를 지정한다.
- 이 값보다 많은 데이터를 저장하면 maxmemory-policy 설정에 지정된 값에 따라서 레디스의 동작이 달라 진다.
maxmemory-policy
: 레디스에서 저장한 데이터가 maxmemory를 넘을 경우, 수행할 정책을 지정한다.
- volatile-lru : 만기시각이 설정된 key 들 중에서 LRU에 의해 key 삭제 (default)
- allkeys-lru : LRU에 의해 key 를 골라 삭제
- volatile-random : 만기시각이 설정된 key 들 중에서 랜덤하게 key 삭제
- allkeys-random : 랜덤하게 key 삭제
- volatile-ttl : 만기시각이 설정된 key 들 중에서 만기가 가장 임박한 key 삭제
- noeviction : 어떤 key 도 삭제하지 않고 error on write operations 를 돌려준다.
maxmemory-samples
: maxmemory-policy를 적용하기 위해 레디스가 조회 할 키의 개수를 지정한다.
- 전체 키를 읽어서 삭제 policy에 해당하는 키를 찾는게 아니라, 지정한 값 만큼의 임의의 키를 읽어서 그 중에서 삭제 대상인 키가 있는지 확인 한다.
- 이때 임의로 읽어 들일 키의 개수를 지정한다.