Redis Replication
Replication? #
Redis의 데이터를 거의 실시간으로 다른 Redis에 복사하는 작업이다. (Redis Cluster)
따라서 서비스를 제공하던 첫 번째 Redis 노드가 다운되더라도, 데이터를 받은 두 번째 Redis 노드가 서비스를 계속할 수 있다. (failover)
Redis에서는 첫 번째 노드를 master 노드라고 하고 두 번째 부터 replica(복제) 노드라고 한다.
복제 기능이 없게 된다면 레디스 인스턴스가 사람의 실수나 소프트웨어적인 문제라 다운되었을 경우 aof 기능을 사용하고 있었고 데이터가 많이 쌓여있게 된다면, 인스턴스가 시작하는 데 몇 분이 걸릴 수 있기 때문에 downtime이 발생하게 되는 문제가 있다.
다운의 원인이 하드웨어적 문제라면? 서비스를 다시 시작하는데 상당한 시간이 소요되며, 데이터를 복구하지 못할 수도 있다.
master, replica는 물리적으로 다른 머신에 두어야 한다.
Redis Replication 특징으로는 다음과 같다.
- Redis는 비동기 복제를 한다.
- Redis는 replica를 여러 개 둘 수 있다.
- 복제 서버는 또 복제 서버를 만들 수 있다. (ex replica1 -> replica2)
- master는 많은 데이터가 있는 상태에서 복제 서버를 시작하면, 대량의 master 데이터가 복제 서버로 보내진다. 이 때도 master는 멈추지 않고 정상적으로 요청을 처리한다.
- 이는 데이터 복제를 서버로 보내는(RDB파일을 생성하는) 작업은 자식 프로세스가 처리하기 때문이다.
- 복제 서버에서 조회요청을 처리하도록 하는 것도 부하 분산에 좋은 방법이다. 특히 sort 같은 명령어들은 복제 서버에서 수행하는 것을 추천한다.
- master에서 부하를 줄이기 위해 AOF 쓰기, RDB 파일 생성을 복제 서버에서 수행하는 것도 좋은 방법이다. 하지만 이런 설정을 했을 경우 master를 자동 시작 하도록 하면 데이터가 유실될 수 있다.
복제 방식 #
redis master, replica의 데이터 동기화, 복제 방식에 대해서 하나씩 알아보도록 하겠다.
전체 동기화 (full synchronization) #
Redis 2.8.18 부터는 RDB 파일을 디스크에 만들지 않고 복제하는 기능을 제공
복제 순서
- master는 자식 프로세스를 시작해 백그라운드 RDB 파일에 데이터를 저장한다.
- 데이터를 저장하는 동안 master에 새로 들어온 명령들은 처리 후 복제 버퍼에 저장한다.
- RDB 파일 저장이 완료되면, master는 파일을 복제 서버에게 전송한다.
- 복제 서버는 파일을 받아 디스크에 저장하고, 메모리로 로드한다.
- master는 복제 버퍼에 저장된 명령을 복제 서버에게 전송한다.
master가 다운되면 복제 서버는 1초에 한번씩 master에 connect request를 보낸다.
master가 살아나게되면 복제 서버에 복제 순서에 따라 sync를 한다.
복제 서버가 여러 개일때도 RDB 파일은 하나만 생성한다.
부분 동기화(Partial Resynchronzation) #
부분 동기화 기능은 Redis 2.8 부터 제공
master, replica는 각각 서버의 run id, replication offset을 가지고 있다.
마스터와 복제 서버간 네트워크가 끊어지게 되면 master는 복제 서버에 전달할 데이터를 backlog-buffer에 저장한다. 다시 연결되었을 때 backlog-buffer가 넘치지 않았으면 run id와 offset을 비교해서 그 이후 부터 동기화를 한다. 이것을 부분 동기화라고 한다.
backlog-buffer의 크기는 repl-backlog-size 파라미터로 설정한다.
네트워크 단절 시간이 길어져 master, backlog-buffer가 넘치면 다시 연결되었을 때 전체 동기화를 한다.
master나 복제 서버 중 한쪽이 재시작 했을 경우에도 전체 동기화를 한다.
master: disk를 사용하지 않는 동기화 #
Redis 버전 2.8.18 부터 디스크를 사용하지 않는 동기화 기능을 제공
이 기능은 redis를 캐시 용도로 사용할 경우 마스터가 설치된 머신의 디스크 성능이 좋지 않을 경우 이용할 수 있다.
- 디스크를 사용하지 않는 것은 master만 적용됨.
- 복제 서버는 받은 데이터를 RDB 파일에 저장한다.
- master의 자식 프로세스가 RDB 데이터 소켓을 통해 복제 서버에게 직접 write하는 방식이다.
redis.conf 파라미터를 통해 설정한다. repl-diskless-sync no or yes, default no
default는 no로 설정되어있고 yes로 설정해야 디스크를 사용하지 않고 동기화된다.
여러 복제 서버에서 요청이 들어올 경우, 기본적으로 첫 번째 복제 서버의 소켓에 데이터를 전송하고, 완료되면, 다음 복제를 처리한다.
몇 개 복제 서버를 한 번에 처리할 수 있도록 요청을 기다리는 옵션도 존재한다. repl-diskless-sync-delay 5 옵션을 조정할 수 있는데 첫 번째 요청이 온 후 5초동안 다른 복제 서버의 요청을 기다렸다가, 요청이 오면 같이 처리한다. 즉, 5초안에 3개의 복제 서버에 동기화 요청이 왔다면 이는 병렬로 수행이 가능하다. 즉시 처리를 원하면 0으로 설정할 수 있다.
replica: disk를 사용하지 않는 동기화 (repl-diskless-load) #
이 기능은 6.0 부터 사용이 가능하다.
복제 서버에서 디스크를 사용하지 않는 동기화다. 작, 복제 서버에 RDB 파일을 생성하지 않는다.
redis.conf의 redis-diskless-load disabled/on-empty-db/swapdb, default disabled 세 가지다.
- disabled: diskless를 사용하지 않음 (디스크를 사용함)
- on-empty-db: 복제 서버에 데이터가 없을 경우 적용, 데이터가 존재하면 RDB 파일을 생성후 복제
- swapdb: 복제 서버에 데이터 여부와 상관없이 diskless로 동작한다. 이 경우 만약의 사태에 대비해서 기존 데이터를 메모리(RAM)에 보존한다. 복제가 성공하면 RAM에 보존한 데이터는 지운다. 복제가 실패하면 RAM에 보존한 데이터로 복구한다. 이 경우 기존 데이터 + 새 데이터 만큼 메모리가 필요하므로 충분한 메모리가 필요하다
이 밖에도 복제서버는 읽기 전용으로만 사용할 수 있는 방법도 존재한다. Redis 2.6부터 redis.conf에 replica-read-only (default no) 옵션을 yes로 설정해서 read only로 사용할 수 있다. 복제 서버에 데이터를 입력 했어도, master와 resync되면 복제 서버에 입력된 데이터는 사라진다.