Redis 복제
Redis 복제 (Replication) (replication-2)
Redis 복제(Redis Cluster나 Redis Sentinel이 추가 레이어로 제공하는 고가용성 기능은 제외)의 기반에는 설정과 사용이 간단한 리더-팔로워(master-replica) 복제가 있어요. 이 복제를 통해 replica Redis 인스턴스는 master 인스턴스의 정확한 사본이 됩니다. replica는 링크가 끊길 때마다 자동으로 master에 다시 연결되며, master에 무슨 일이 일어나든 정확한 사본이 되도록 시도해요.
이 시스템은 세 가지 주요 메커니즘으로 동작합니다.
- master와 replica 인스턴스가 잘 연결되어 있으면, master는 replica에 명령 스트림을 보내 데이터셋에 대한 효과를 복제해 replica를 최신 상태로 유지해요. 이 효과에는 클라이언트 쓰기, 만료되거나 축출된 키, master 데이터셋을 변경하는 기타 모든 작업이 포함됩니다.
- 네트워크 문제나 master/replica의 타임아웃 감지 등으로 링크가 끊어지면, replica는 다시 연결해 부분 재동기화(partial resynchronization) 를 시도합니다. 이는 연결이 끊긴 동안 놓친 명령 스트림 부분만 얻으려 한다는 뜻이에요.
- 부분 재동기화가 불가능하면 replica는 전체 재동기화(full resynchronization) 를 요청합니다. 이는 더 복잡한 과정으로, master가 모든 데이터의 스냅샷을 만들고 replica로 보낸 다음 데이터셋이 변경됨에 따라 명령 스트림을 계속 보내야 해요.
Redis는 기본적으로 비동기 복제(asynchronous replication) 를 사용하는데, 이는 지연 시간이 낮고 성능이 높아 대부분의 Redis 사용 사례에 자연스러운 복제 모드예요. 다만 Redis replica는 처리한 데이터 양을 master에 주기적으로 비동기적으로 확인(acknowledge)합니다. 그래서 master는 replica가 명령을 처리할 때마다 매번 기다리지 않지만, 필요하다면 어떤 replica가 어떤 명령을 이미 처리했는지 알 수 있어요. 이를 통해 선택적 동기식 복제가 가능해집니다.
특정 데이터의 동기식 복제는 클라이언트가 WAIT 명령으로 요청할 수 있어요. 그러나 WAIT는 다른 Redis 인스턴스에 지정된 수만큼의 확인된 사본이 존재하도록 보장할 뿐이며, 인스턴스 집합을 강한 일관성을 가진 CP 시스템으로 바꾸지는 않습니다. Redis 영속성(persistence) 구성에 따라 페일오버 중에 확인된 쓰기가 여전히 유실될 수 있어요. 다만 WAIT는 실패 이벤트 후 쓰기가 유실될 확률을 특정하고 발동하기 어려운 실패 모드로 크게 줄여 줍니다.
고가용성과 페일오버에 대한 자세한 내용은 Redis Sentinel 또는 Redis Cluster 문서를 확인해 주세요. 이 문서의 나머지 부분은 주로 Redis 기본 복제의 기본 특성을 설명합니다.
Redis 복제에 관한 중요한 사실
- Redis는 비동기 복제를 사용하며, 처리된 데이터 양에 대한 replica→master의 비동기 확인을 사용해요.
- master는 여러 replica를 가질 수 있어요.
- replica는 다른 replica로부터 연결을 받을 수 있어요. 여러 replica를 같은 master에 연결하는 것 외에도 replica를 다른 replica에 연결해 캐스케이드(cascading) 구조를 만들 수도 있습니다. Redis 4.0부터 모든 하위 replica(sub-replica)는 master로부터 정확히 동일한 복제 스트림을 받아요.
- Redis 복제는 master 쪽에서 논블로킹(non-blocking)입니다. 하나 이상의 replica가 초기 동기화나 부분 재동기화를 수행하는 동안에도 master는 계속 쿼리를 처리한다는 뜻이에요.
- 복제는 replica 쪽에서도 대체로 논블로킹입니다. replica가 초기 동기화를 수행하는 동안 redis.conf에서 그렇게 구성했다면 이전 버전 데이터셋으로 쿼리를 처리할 수 있어요. 그렇지 않으면 복제 스트림이 끊어졌을 때 오류를 반환하도록 구성할 수도 있습니다. 다만 초기 동기화 후에는 이전 데이터셋을 삭제하고 새 데이터셋을 로드해야 해요. 이 짧은 구간(매우 큰 데이터셋의 경우 수 초까지 걸릴 수 있음) 동안 replica는 들어오는 연결을 차단합니다. Redis 4.0부터 이전 데이터 삭제를 다른 스레드에서 수행하도록 구성할 수 있지만, 새 초기 데이터셋 로드는 여전히 메인 스레드에서 일어나 replica를 차단해요.
- 복제는 확장성(scalability)을 위해, 즉 느린 O(N) 연산 같은 읽기 전용 쿼리를 위해 여러 replica를 두는 데 사용할 수 있고, 단순히 데이터 안전성과 고가용성을 높이기 위해서도 사용할 수 있어요.
- 복제를 사용하면 master가 전체 데이터셋을 디스크에 쓰는 비용을 피할 수 있어요. 일반적인 기법은 master의 redis.conf를 구성해 디스크에 전혀 영속화하지 않고, 가끔 저장하도록 구성된 replica나 AOF가 활성화된 replica를 연결하는 것입니다. 다만 이 구성은 주의해서 다뤄야 해요. 재시작된 master는 빈 데이터셋으로 시작하므로, replica가 그 master와 동기화하려 하면 replica도 비워지게 됩니다.
master의 영속성이 꺼져 있을 때 복제의 안전성
Redis 복제를 사용하는 구성에서는 master와 replica 모두에서 영속성을 켜 두는 것을 강력히 권장합니다. 이것이 불가능한 경우, 예를 들어 매우 느린 디스크로 인한 지연 문제라면, 인스턴스가 재부팅 후 자동으로 재시작되지 않도록 구성해야 해요.
영속성이 꺼진 master가 자동 재시작하도록 구성된 것이 왜 위험한지 이해하기 위해, master와 모든 replica에서 데이터가 지워지는 다음 실패 모드를 살펴볼게요.
- 노드 A가 master 역할을 하고 영속성이 꺼져 있으며, 노드 B와 C가 노드 A로부터 복제하는 구성이 있습니다.
- 노드 A가 크래시하지만, 프로세스를 재시작하는 자동 재시작 시스템이 있어요. 다만 영속성이 꺼져 있으므로 노드는 빈 데이터셋으로 재시작됩니다.
- 노드 B와 C는 (빈 상태인) 노드 A로부터 복제하므로, 사실상 자신의 데이터 사본을 파괴하게 됩니다.
고가용성을 위해 Redis Sentinel을 사용할 때도 master에서 영속성을 끄고 프로세스 자동 재시작을 켜는 것은 위험합니다. 예를 들어 master가 Sentinel이 실패를 감지하지 못할 만큼 빠르게 재시작되어 위 실패 모드가 발생할 수 있어요.
데이터 안전성이 중요하고, master가 영속성 없이 복제를 사용하는 구성이라면 인스턴스의 자동 재시작을 비활성화해야 합니다.
Redis 복제가 동작하는 방식
모든 Redis master는 복제 ID(replication ID) 를 가집니다. 이는 데이터셋의 특정 히스토리를 표시하는 큰 의사 난수 문자열이에요. 또한 각 master는 데이터셋을 변경하는 새 변경 사항으로 replica 상태를 갱신하기 위해 replica로 보낼 복제 스트림의 바이트마다 증가하는 오프셋(offset) 을 가집니다. 복제 오프셋은 실제로 연결된 replica가 없어도 증가하므로, 기본적으로 다음의 각 쌍은:
Replication ID, 오프셋
master 데이터셋의 정확한 버전을 식별합니다.
replica가 master에 연결하면 PSYNC 명령으로 이전 master의 복제 ID와 지금까지 처리한 오프셋을 보내요. 이렇게 하면 master는 필요한 증분 부분만 보낼 수 있어요. 다만 master 버퍼에 백로그(backlog) 가 충분하지 않거나, replica가 더 이상 알려지지 않은 히스토리(복제 ID)를 참조한다면 전체 재동기화가 발생합니다. 이 경우 replica는 처음부터 데이터셋의 전체 사본을 받아요.
전체 동기화가 좀 더 자세히 동작하는 방식은 다음과 같습니다.
- master는 RDB 파일을 만들기 위해 백그라운드 저장 프로세스를 시작합니다. 동시에 클라이언트로부터 받은 모든 새 쓰기 명령을 버퍼링하기 시작해요.
- 백그라운드 저장이 완료되면 master는 데이터베이스 파일을 replica로 전송하고, replica는 이를 디스크에 저장한 다음 메모리에 로드합니다.
- master는 이후 모든 버퍼링된 명령을 replica로 보내요. 이는 명령 스트림으로 수행되며 Redis 프로토콜 자체와 동일한 형식입니다.
텔넷으로 직접 시도해 볼 수 있어요. 서버가 작업을 하는 동안 Redis 포트에 연결하고 SYNC 명령을 내리세요. 벌크 전송이 일어난 다음 master가 받은 모든 명령이 텔넷 세션에서 다시 실행되는 것을 볼 수 있어요. 실제로 SYNC는 더 이상 최신 Redis 인스턴스에서 사용되지 않는 오래된 프로토콜이지만, 하위 호환성을 위해 여전히 남아 있어요. SYNC는 부분 재동기화를 허용하지 않으므로 이제는 PSYNC가 대신 사용됩니다.
앞서 말했듯이 replica는 어떤 이유로 master-replica 링크가 끊어지면 자동으로 다시 연결할 수 있어요. master가 여러 동시 replica 동기화 요청을 받으면 단일 백그라운드 저장을 수행해 모두를 처리합니다.
복제 ID 설명
이전 절에서 두 인스턴스가 동일한 복제 ID와 복제 오프셋을 가지면 정확히 동일한 데이터를 가진다고 했어요. 다만 복제 ID가 정확히 무엇인지, 그리고 인스턴스가 실제로 두 개의 복제 ID(메인 ID와 세컨더리 ID)를 가지는 이유를 이해하는 것이 유용합니다.
복제 ID는 기본적으로 데이터셋의 특정 히스토리(history) 를 표시해요. 인스턴스가 master로서 처음부터 재시작되거나 replica가 master로 승격될 때마다 이 인스턴스를 위해 새 복제 ID가 생성됩니다. master에 연결된 replica는 핸드셰이크 후 그 복제 ID를 상속해요. 따라서 동일한 ID를 가진 두 인스턴스는 동일한 데이터를 보유한다는 점에서 관련이 있지만, 시점은 다를 수 있어요. 특정 히스토리(복제 ID)에 대해 누가 가장 최신 데이터셋을 보유하는지 이해하기 위한 논리적 시간으로 동작하는 것은 바로 오프셋입니다.
예를 들어 인스턴스 A와 B가 동일한 복제 ID를 가지지만 하나는 오프셋 1000, 다른 하나는 오프셋 1023이라면, 첫 번째 인스턴스에는 데이터셋에 적용된 특정 명령이 없다는 뜻이에요. 또한 A가 몇 개의 명령만 적용해 B와 정확히 같은 상태에 도달할 수 있음을 의미합니다.
Redis 인스턴스가 두 개의 복제 ID를 가지는 이유는 master로 승격된 replica 때문입니다. 페일오버 후 승격된 replica는 이전의 복제 ID를 계속 기억해야 하는데, 그 복제 ID가 이전 master의 복제 ID였기 때문이에요. 이렇게 하면 다른 replica가 새 master와 동기화할 때 이전 master 복제 ID를 사용해 부분 재동기화를 시도할 것입니다. replica가 master로 승격될 때 세컨더리 ID를 메인 ID로 설정하고 이 ID 전환이 일어난 시점의 오프셋을 기억하므로, 이는 예상대로 동작해요. 이후 새 히스토리가 시작되므로 새 무작위 복제 ID를 선택합니다. 새 replica가 연결될 때 master는 현재 ID와 세컨더리 ID 모두와 그들의 ID 및 오프셋을(안전을 위해 주어진 오프셋까지) 일치시킵니다. 간단히 말해 페일오버 후 새로 승격된 master에 연결되는 replica는 전체 동기화를 수행할 필요가 없습니다.
승격된 replica가 페일오버 후 복제 ID를 변경해야 하는 이유가 궁금할 수 있어요. 네트워크 파티션 때문에 이전 master가 여전히 master로 동작하고 있을 가능성이 있기 때문입니다. 동일한 복제 ID를 유지하면 임의의 두 인스턴스가 동일한 ID와 동일한 오프셋을 가질 때 동일한 데이터셋을 가진다는 규칙을 위반하게 돼요.
디스크리스 복제 (Diskless replication)
일반적으로 전체 재동기화는 RDB 파일을 디스크에 만들고, 그 RDB를 디스크에서 다시 로드해 replica에 데이터를 공급해야 합니다.
느린 디스크에서는 이것이 master에 매우 스트레스를 주는 작업이 될 수 있어요. Redis 2.8.18은 디스크리스 복제를 지원한 첫 번째 버전입니다. 이 구성에서는 자식 프로세스가 디스크를 중간 저장소로 사용하지 않고 RDB를 와이어(wire)를 통해 직접 replica로 보냅니다.
구성 (Configuration)
기본 Redis 복제를 구성하는 것은 간단해요. replica 설정 파일에 다음 줄을 추가하기만 하면 됩니다.
replicaof 192.168.1.1 6379
물론 192.168.1.1 6379를 master IP 주소(또는 호스트명)와 포트로 바꿔야 해요. 또는 REPLICAOF 명령을 호출하면 master 호스트가 replica와 동기화를 시작합니다.
부분 재동기화를 위해 master가 메모리에 보관하는 복제 백로그를 조정하는 몇 가지 파라미터도 있어요. 자세한 내용은 Redis 배포판에 포함된 예제 redis.conf를 참조하세요.
디스크리스 복제는 repl-diskless-sync 구성 파라미터로 활성화할 수 있어요. 첫 replica가 도착한 후 더 많은 replica가 도착하기를 기다리는 전송 시작 지연은 repl-diskless-sync-delay 파라미터로 제어합니다. 자세한 내용은 Redis 배포판의 예제 redis.conf 파일을 참조하세요.
읽기 전용 replica (Read-only replica)
Redis 2.6부터 replica는 기본적으로 활성화되는 읽기 전용 모드를 지원합니다. 이 동작은 redis.conf 파일의 replica-read-only 옵션으로 제어되며, CONFIG SET으로 런타임에 활성화/비활성화할 수 있어요.
읽기 전용 replica는 모든 쓰기 명령을 거부하므로 실수로 replica에 쓰는 것이 불가능합니다. 다만 이것이 replica 인스턴스를 인터넷이나 신뢰할 수 없는 클라이언트가 존재하는 네트워크에 노출시키기 위한 기능은 아니에요. DEBUG나 CONFIG 같은 관리 명령은 여전히 활성화되어 있기 때문입니다. Security 페이지에서 Redis 인스턴스를 보호하는 방법을 설명합니다.
읽기 전용 설정을 되돌리고 쓰기 작업의 대상이 될 수 있는 replica를 만드는 것이 왜 가능한지 궁금할 수 있어요. 답은 쓰기 가능한 replica(writable replica)가 역사적 이유로만 존재한다는 것입니다. 쓰기 가능한 replica는 master와 replica 사이에 불일치를 발생시킬 수 있으므로 권장하지 않아요. 어떤 상황에서 문제가 될 수 있는지 이해하려면 복제가 어떻게 동작하는지 이해해야 합니다. master의 변경 사항은 일반 Redis 명령을 replica로 전파해 복제됩니다. master에서 키가 만료되면 DEL 명령으로 전파돼요. master에 존재하지만 replica에서 삭제되었거나, 만료되었거나, master와 다른 타입인 키는 master에서 전파된 DEL, INCR, RPOP 같은 명령에 대해 의도한 것과 다르게 반응할 수 있어요. 전파된 명령이 replica에서 실패하거나 다른 결과를 낼 수 있습니다. 위험을 최소화하려면(쓰기 가능한 replica를 꼭 사용한다면) 다음 권장사항을 따르길 권합니다.
- 쓰기 가능한 replica에서 master에서도 사용되는 키에는 쓰지 마세요. (master에 쓰는 모든 클라이언트를 제어할 수 없다면 보장하기 어려울 수 있어요.)
- 실행 중인 시스템에서 인스턴스 집합을 업그레이드할 때 중간 단계로 인스턴스를 쓰기 가능한 replica로 구성하지 마세요. 일반적으로 데이터 일관성을 보장하려면 master로 승격될 수 있는 인스턴스를 쓰기 가능한 replica로 구성하지 마세요.
역사적으로 쓰기 가능한 replica에 대해 합법적이라고 여겨졌던 몇 가지 사용 사례가 있었습니다. 버전 7.0부터 이러한 사용 사례는 모두 더 이상 사용되지 않으며 동일한 작업을 다른 방법으로 달성할 수 있어요. 예를 들면:
SUNIONSTORE,ZINTERSTORE같은 명령으로 느린 Set 또는 Sorted set 연산을 계산하고 그 결과를 임시 로컬 키에 저장하는 것. 대신SUNION,ZINTER처럼 결과를 저장하지 않고 반환하는 명령을 사용하세요.SORT명령 사용(선택적STORE옵션 때문에 읽기 전용 명령으로 간주되지 않으므로 읽기 전용 replica에서 사용할 수 없음). 대신 읽기 전용 명령인SORT_RO를 사용하세요.EVAL과EVALSHA도 Lua 스크립트가 쓰기 명령을 호출할 수 있으므로 읽기 전용 명령으로 간주되지 않아요. 대신 Lua 스크립트가 읽기 전용 명령만 호출할 수 있는EVAL_RO와EVALSHA_RO를 사용하세요.
replica와 master가 재동기화되거나 replica가 재시작되면 replica에 대한 쓰기는 버려지지만, 자동으로 동기화된다는 보장은 없습니다.
4.0 이전 버전에서 쓰기 가능한 replica는 TTL(time to live)이 설정된 키를 만료시킬 수 없었어요. 즉 EXPIRE나 다른 TTL 최대값을 설정하는 명령을 사용하면 키가 누출되며, 읽기 명령으로 접근할 때는 보이지 않을지라도 키 개수에는 나타나고 메모리를 계속 사용하게 됩니다. Redis 4.0 RC3 이상 버전은 DB 번호가 63보다 큰 키(기본적으로 Redis 인스턴스는 16개의 데이터베이스만 가짐)를 제외하고 master처럼 TTL이 있는 키를 축출할 수 있어요. 단, 4.0보다 큰 버전에서도 master에 존재할 수 있는 키에 EXPIRE를 사용하면 replica와 master 사이에 불일치가 발생할 수 있습니다.
또한 Redis 4.0부터 replica 쓰기는 로컬에만 존재하며 인스턴스에 연결된 하위 replica로는 전파되지 않아요. 대신 하위 replica는 항상 최상위 master가 중간 replica로 보낸 것과 동일한 복제 스트림을 받습니다. 예를 들어 다음 구성에서:
A ---> B ---> C
B가 쓰기 가능하더라도 C는 B의 쓰기를 보지 못하고, 대신 master 인스턴스 A와 동일한 데이터셋을 가지게 됩니다.
replica가 master에 인증하도록 설정
master가 requirepass로 비밀번호를 가진다면, 모든 동기화 작업에서 replica가 그 비밀번호를 사용하도록 구성하는 것은 간단합니다.
실행 중인 인스턴스에서 하려면 redis-cli를 사용해 다음을 입력하세요.
config set masterauth <password>
영구적으로 설정하려면 설정 파일에 다음을 추가하세요.
masterauth <password>
N개의 연결된 replica가 있을 때만 쓰기 허용
Redis 2.8부터, 최소 N개의 replica가 현재 master에 연결되어 있을 때만 Redis master가 쓰기 쿼리를 수락하도록 구성할 수 있어요.
다만 Redis는 비동기 복제를 사용하므로 replica가 주어진 쓰기를 실제로 받았는지 보장할 수 없기 때문에 항상 데이터 유실의 여지가 있습니다.
이 기능이 동작하는 방식은 다음과 같아요.
- Redis replica는 매초 master에 ping을 보내며 처리된 복제 스트림의 양을 확인합니다.
- Redis master는 모든 replica로부터 ping을 마지막으로 받은 시간을 기억해요.
- 사용자는 지연(lag)이 최대 초 수를 초과하지 않는 최소 replica 수를 구성할 수 있습니다.
지연이 M초 미만인 replica가 최소 N개 이상 있으면 쓰기가 수락됩니다.
이를 최선의 노력(best effort) 데이터 안전성 메커니즘으로 생각할 수 있어요. 특정 쓰기에 대해 일관성이 보장되지는 않지만, 데이터 유실 시간 창이 특정 초 수로 제한됩니다. 일반적으로 유실을 묶는 것(bound)이 묶지 않는 것(unbound)보다 낫습니다.
조건이 충족되지 않으면 master는 오류로 응답하며 쓰기가 수락되지 않습니다.
이 기능에는 두 가지 구성 파라미터가 있습니다.
min-replicas-to-write <number of replicas>min-replicas-max-lag <number of seconds>
자세한 내용은 Redis 소스 배포판에 포함된 예제 redis.conf 파일을 확인하세요.
Redis 복제가 키 만료를 처리하는 방식
Redis 만료(expires)는 키가 제한된 TTL(time to live)을 갖도록 허용합니다. 이러한 기능은 인스턴스가 시간을 세는 능력에 의존하지만, Redis replica는 Lua 스크립트를 사용해 키가 변경되는 경우에도 만료가 있는 키를 올바르게 복제해요.
이 기능을 구현하기 위해 Redis는 master와 replica가 동기화된 클럭을 가지는 능력에 의존할 수 없어요. 이는 해결할 수 없는 문제이며 레이스 컨디션과 데이터셋 분기를 초래할 수 있기 때문입니다. 그래서 Redis는 만료된 키의 복제가 동작하도록 세 가지 주요 기법을 사용합니다.
- replica는 키를 만료시키지 않고, 대신 master가 키를 만료시킬 때까지 기다려요. master가 키를 만료시키거나 LRU로 인해 축출하면, replica에 전송되는
DEL명령을 합성합니다. - 그러나 master 주도 만료(master-driven expire) 때문에, master가 제때
DEL명령을 제공하지 못해 replica에 논리적으로는 이미 만료된 키가 여전히 메모리에 존재할 수 있어요. 이를 처리하기 위해 replica는 논리적 클럭을 사용하여 데이터셋의 일관성을 위반하지 않는 읽기 작업에 대해서만 키가 존재하지 않는다고 보고합니다(새 명령이 master로부터 도착할 때). 이렇게 하면 replica가 여전히 존재하는 논리적으로 만료된 키를 보고하지 않게 됩니다. 실질적으로, replica로 확장하는 HTML 프래그먼트 캐시는 원하는 TTL보다 이미 오래된 항목을 반환하는 것을 피할 수 있어요. - Lua 스크립트 실행 중에는 키 만료가 수행되지 않습니다. Lua 스크립트가 실행되는 동안 개념적으로 master의 시간은 고정되므로, 주어진 키는 스크립트가 실행되는 동안 존재하거나 존재하지 않습니다. 이는 스크립트 도중 키가 만료되는 것을 방지하며, 동일한 스크립트를 replica로 보내 데이터셋에 동일한 효과가 있음을 보장하는 데 필요합니다.
replica가 master로 승격되면 독립적으로 키를 만료시키기 시작하며, 이전 master의 도움이 필요하지 않습니다.
Docker와 NAT에서의 복제 구성
Docker 또는 포트 포워딩을 사용하는 다른 컨테이너나 NAT(Network Address Translation)를 사용할 때, 특히 master INFO나 ROLE 명령 출력을 스캔해 replica 주소를 발견하는 Redis Sentinel이나 다른 시스템을 사용할 때 Redis 복제는 추가적인 주의가 필요합니다.
문제는 ROLE 명령과 INFO 출력의 복제 섹션이 master 인스턴스에서 실행될 때 replica가 master에 연결하는 데 사용하는 IP 주소로 replica를 표시한다는 것입니다. NAT를 사용하는 환경에서는 이 주소가 replica 인스턴스의 논리적 주소(클라이언트가 replica에 연결하는 데 사용해야 하는 주소)와 다를 수 있어요.
마찬가지로 replica는 redis.conf에 구성된 수신 포트로 나열되는데, 포트가 리맵된 경우 전달된 포트와 다를 수 있습니다.
두 문제를 모두 해결하기 위해, Redis 3.2.2부터 replica가 master에 임의의 IP와 포트 쌍을 알리도록 강제할 수 있어요. 사용할 두 가지 구성 지시문은:
replica-announce-ip 5.5.5.5
replica-announce-port 1234
이며, 최신 Redis 배포판의 예제 redis.conf에 문서화되어 있습니다.
INFO 및 ROLE 명령
master와 replica 인스턴스의 현재 복제 파라미터에 대한 많은 정보를 제공하는 두 가지 Redis 명령이 있어요. 하나는 INFO입니다. INFO replication처럼 replication 인수를 사용해 명령을 호출하면 복제와 관련된 정보만 표시됩니다. 또 다른 더 컴퓨터 친화적인 명령은 ROLE로, master와 replica의 복제 상태를 복제 오프셋과 함께, 연결된 replica 목록 등을 제공합니다.
재시작 후 및 페일오버 후 부분 동기화
Redis 4.0부터 인스턴스가 페일오버 후 master로 승격되면 이전 master의 replica와 부분 재동기화를 여전히 수행할 수 있어요. 이를 위해 replica는 이전 master의 이전 복제 ID와 오프셋을 기억하므로, 연결하는 replica가 이전 복제 ID를 요청하더라도 백로그의 일부를 제공할 수 있습니다.
다만 승격된 replica의 새 복제 ID는 데이터셋의 다른 히스토리를 구성하므로 달라집니다. 예를 들어 master가 다시 사용 가능해져 일정 시간 쓰기를 계속 수락할 수 있다면, 승격된 replica에서 동일한 복제 ID를 사용하는 것은 복제 ID와 오프셋 쌍이 단일 데이터셋만 식별한다는 규칙을 위반하기 때문입니다.
또한 replica는 부드럽게 전원이 꺼지고 재시작될 때 master와 재동기화하는 데 필요한 정보를 RDB 파일에 저장할 수 있어요. 이는 업그레이드 경우에 유용합니다. 필요할 때 replica에서 save & quit 작업을 수행하기 위해 SHUTDOWN 명령을 사용하는 것이 좋습니다.
AOF 파일을 통해 재시작된 replica는 부분 동기화할 수 없습니다. 다만 종료 전에 인스턴스를 RDB 영속성으로 바꾼 다음 재시작하고 마지막으로 AOF를 다시 활성화할 수 있어요.
replica의 Maxmemory
기본적으로 replica는 maxmemory를 무시합니다(페일오버 후 master로 승격되거나 수동으로 승격되지 않는 한). 이는 키의 축출이 master에 의해 처리되고, master 쪽에서 키가 축출됨에 따라 DEL 명령을 replica로 보낸다는 뜻입니다.
이 동작은 master와 replica가 일관성을 유지하도록 보장하며, 보통 원하는 결과입니다. 다만 replica가 쓰기 가능하거나 replica에 다른 메모리 설정을 원하고, replica에 수행되는 모든 쓰기가 멱등(idempotent)하다고 확신한다면 이 기본값을 변경할 수 있어요(그러나 무엇을 하는지 확실히 이해해야 합니다).
replica는 기본적으로 축출하지 않으므로 maxmemory로 설정된 것보다 더 많은 메모리를 사용할 수 있습니다(replica에서 더 클 수 있는 특정 버퍼나 데이터 구조가 때로 더 많은 메모리를 차지할 수 있기 때문). replica를 모니터링하고 master가 구성된 maxmemory 설정에 도달하기 전에 실제 메모리 부족(out-of-memory) 상태에 절대 도달하지 않도록 충분한 메모리가 있는지 확인하세요.
이 동작을 변경하려면 replica가 maxmemory를 무시하지 않도록 허용할 수 있어요. 사용할 구성 지시문은:
replica-ignore-maxmemory no
출처: 공식문서