MySQL Replica 동기화 방식과 토폴로지

saewoohan·2025년 3월 24일

MySQL

목록 보기
8/9
post-thumbnail

MySQL에서 복제는 단순히 “데이터를 복사한다”는 개념을 넘어, 데이터를 어떤 방식으로, 어떤 구조로, 얼마나 안정적으로 전달하느냐에 따라 그 성격이 크게 달라진다.

복제 동기화 방식

복제는 Master가 데이터를 처리한 시점과, Replica가 그 데이터를 수신, 적용 하는 시점 간의 타이밍에 따라 비동기 복제와 반동기 복제로 나눌 수 있다.

비동기 복제

MySQL의 복제는 기본적으로 비동기 방식으로 동작한다. 이는 말 그대로 소스 서버가 레플리카 서버에서 변경 이벤트가 정상적으로 전달되어 적용됐는지를 확인하지 않는 방식이다.

즉, 소스 서버 입장에서는 복제가 잘 되었는지 아닌지는 관심이 없고 단순히 binary log만 남기고 나머지는 Replica가 알아서 처리하는 것이다.

🚧 동작 흐름
1. 클라이언트가 Source에 트랜잭션 전송
2. Source는 트랜잭션을 처리하고 binary log에 기록
3. Source는 클라이언트에 응답
4. Replica는 binary log를 읽고 relay log에 기록
5. Relay log를 기반으로 Replica에 적용

하지만, 비동기 복제는 큰 단점이 존재하는데 소스 서버에 장애가 발생하면 소스 서버에서 최근까지 적용된 트랜잭션이 레플리카 서버로 전달되지 않을 수 있다. 즉, 누락된 트랜잭션이 존재할 수 있는 것이다.
그렇기에 소스 서버 장애로 인해서 레플리카 서버가 새로운 소스 서버로 승격되는 경우, 사용자는 레플리카 서버가 소스 서버로부터 전달받지 못한 트랜잭션이 있는지 확인하고 있다면 수동으로 다시 적용해야 한다.

하지만, 레플리카 서버의 응답을 고려하지 않기에 아무래도 트랜잭션 처리에 빠른 성능을 보이며 레플리카 서버의 성능 저하가 있더라고 소스 서버와는 무관한 장점들이 존재하다.

⧴ 복제 지연
비동기 복제는 Replica가 Master보다 뒤처질 수 있다. 이를 복제 지연이라고 부르며, 일반적으로 짧은 시간내에 레플리카 서버에도 적용되기 때문에 큰 문제는 없다. 하지만, 즉각적으로 반영된 데이터를 조회해야하는 경우에는 소스 서버로 부터 읽도록 구성해야 한다.

반동기 복제

반동기 복제는 비동기 복제보다 좀 더 향상된 데이터 무결성을 제공하는 복제 동기화 방식이다. 비동기 복제는 소스가 클라이언트에게 결과를 반환할 때, Replica가 해당 트랜잭션을 수신했는지 여부와 관계 없이 커밋을 처리하지만, 반동기 복제는 추가 조건을 가진다.

Source는 트랜잭션 커밋 이후, 적어도 하나의 Replica로 부터 binary log ACK를 받은 후에야 결과를 반환.

여기서 중요한 점은 레플리카 서버에 “전송”되었음을 보장하는 것이지, “적용”까지 보장하는 것은 아니다. 그래서 이름이 반동기인 것이다.

🚧 동작 흐름
1. 클라이언트가 Source에 트랜잭션 전송
2. Source는 트랜잭션을 처리하고 binary log에 기록
3. Replica는 binary log를 읽고 relay log에 기록
4. Replica는 ACK를 Master에 전송
5. Master는 클라이언트에 커밋 성공 응답

여기서 추가로 소스 서버가 레플리카 서버의 응답을 기다리는 시점에 따라 AFTER_SYNCAFTER_COMMIT으로 각각 동작을 설정할 수 있다.

AFTER_COMMIT

AFTER_COMMIT은 소스 서버에서 트랜잭션을 Binary log에 기록하고 스토리지 엔진에서의 커밋도 진행하고 나서 최종적으로 클라이언트에 결과를 반환하기 전에 레플리카 서버의 응답을 기다린다. 레플리카 서버로부터 ACK를 받으면 그때 클라이언트는 처리 결과를 얻을 수 있는 것이다.

AFTER_SYNC

AFTER_SYNC는 소스 서버에서는 각 트랜잭션을 Binary log에 기록하고 난 후 스토리지 엔진에 커밋하기 전 단계에서 레플리카 서버의 응답을 기다린다. 레플리카 서버에서 ACK가 도착하면 그때 스토리지 엔진을 커밋해서 트랜잭션에 대한 처리를 끝낸 후 클라이언트에게 결과를 반환한다.

과거에는 AFTER_COMMIT으로만 동작했지만, 현재는 기본 동작 방식이 AFTER_SYNC으로 변경되었다. 그 이유는 AFTER_SYNCAFTER_COMMIT과 비교하여 얻는 장점이 존재하기 때문이다.

  • 소스 서버에서 장애가 발생했을 때 Phantom Read가 없음
  • 장애가 발생한 소스 서버에 대한 복구가 조금 더 쉬움

AFTER_COMMIT은 트랜잭션이 스토리지 엔진 커밋(실제 데이터 반영) 까지 끝난 후 레플리카 서버의 응답을 기다린다. 이로 인해서, 소스 서버가 레플리카 서버로부터 아직 응답을 기다리고 있는 상황에서 장애가 발생한 경우, 새로 소스 서버로 승격한 레플리카 서버에서는 이전 소스 서버에 존재했던 데이터를 조회하지 못할 수 있다.

하지만, AFTER_SYNC는 레플리카를 기다린 후 스토리지 엔진에 커밋하기에 이러한 문제는 발생하지 않는다.

또한, 앞선 상황에서 소스 서버를 재사용하는 경우 AFTER_COMMIT은 이렇게 Phantom Read가 발생한 트랜잭션들을 수동으로 롤백을 시켜야하지만, AFTER_SYNC는 애초에 반영이 안되었기에 그럴 필요가 없다.

복제 토폴로지

복제의 안정성과 확장성은 토폴로지를 어떻게 구성하느냐에 따라서 또 크게 달라지며, MySQL은 다양한 복제 구조를 지원하며, 운영 목적과 규모에 맞는 구성을 선택하는 것이 매우 중요하다.

싱글 레플리카

싱글 레플리카 복제는 그림과 같이 하나의 소스 서버에 하나의 레플리카 서버만 연결되어 있는 형태를 말한다.

가장 단순한 복제 구성으로 주로 백업 용도 혹은, 단순 읽기 부하 분산 목적으로 사용된다. 만약 이 형태에서 레플리카에 읽기 쿼리를 많이 주게 된다면, 레플리카에 장애가 발생한 경우 서비스 장애 상황이 발생할 수 도 있다. 그렇기에, 싱글 레플리카 토폴로지에서는 정말 예비용 서버로 두는 것이 적합한 목적이다.

멀티 레플리카

멀티 레플리카는 하나의 소스 서버에 2개 이상의 레플리카 서버를 연결한 복제 형태이다.

읽기 트래픽을 레플리카 서버에 효율적으로 분산할 수 있으며, 장애 복구 시 빠르게 다른 레플리카를 승격하여 고가용성을 보장할 수 있다.

체인 레플리카

만약, 멀티 레플리카 복제 구성에서 레플리카 서버가 너무 많아 소스 서버의 성능에 악영향을 미친다면, 1:M:M 구조의 체인 복제 구성을 고려할 수 있다.

MySQL 복제에서 소스 서버는 레플리카 서버가 요청할 때마다 계속 Binary log를 읽어서 전달해야하기에, 레플리카 서버의 수가 많다면 Binary log를 읽는 작업이 부하가 될 수 있다.

위의 그림처럼 레플리카가 또 다른 레플리카의 Source 역할을 수행하며, 하나의 소스에 연결되는 복제 연결 수를 줄일 수 있다.

또한, 이 토폴로지는 MySQL 서버의 업그레이드나 장비 교체에도 많이 사용된다.

위 그림처럼 신 장비로 이루어진 새로운 복제 토폴로지를 추가해서 기존 도메인 네임이나 IP 주소를 이 새로운 MySQL 서버들을 바라보게끔 변경하면, 모두 새로운 MySQL 서버들로 전달 된다.

그 이후 이전에 존재하던 MySQL 서버들을 그룹에서 제거하기만 하면 새로운 장비로 이루어진 MySQL로의 마이그레이션이 가능하다.

듀얼 소스 레플리카

듀얼 소스 레플리카 구성은 두 개의 MySQL 서버가 서로 소스 서버이자 레플리카 서버로 구성되어 있는 형태이다.

각 서버에서 변경한 데이터는 다시 복제를 통해 양 서버에 적용되므로 동일한 데이터를 갖게 된다. 목적에 따라 ACTIVE-PASSIVE , ACTIVE-ACTIVE 로 각각 구성하는데 ACTIVE는 쓰기 처리하는 서버를 말하는 것이다.

즉, ACTIVE-PASSIVE는 한쪽 Source만 쓰기 처리하는 것인데 싱글 레플리카와 비슷하지만 다른 쪽에서 바로 쓰기 작업을 전환할 수 있다는 것이 다르다.

하지만, ACTIVE-ACTIVE는 두 소스 서버에서 모두 쓰기가 가능하며 지리적 이중화나 무중단 서비스에 유리하다. 서로 다른 지역에 MySQL 서버를 두고 각 지역에서 발생하는 쓰기 요청은 해당 지역의 서버에서 수행되도록 하면 조금 더 빠른 쓰기 처리가 가능한 것이다.

양쪽에서 쓰기가 가능하기에 문제가 발생할 수 있는데, 동일한 데이터에 대한 변경이 각 MySQL 서버에 동시점에 유입되는 경우 실제 쿼리 순서와는 다른 순서로 데이터가 최종적으로 업데이트 될 수 있다. 원래 하나의 MySQL 서버에 쓰기를 한다면 잠금으로 인해 순차적 처리가 가능하지만 그렇지 못한 것이다.

또한, Auto-Increment 키에 대해서 동일한 시점에 새로운 데이터가 양쪽 MySQL 서버로 유입되면 같은 키 값을 가지게 될 수 있으며, 에러가 발생할 수 있다. 이러한 상황을 방지하기 위해 auto_increment_offset 시스템 변수를 통해 서버의 개수 만큼 증분 값을 늘려주던가, UUID와 ULID 같은 글로벌한 값을 사용하는 것이 좋다.

멀티 소스 레플리카

멀티 소스 레플리카는 그림처럼 하나의 레플리카가 둘 이상의 소스 서버를 갖는 형태를 말한다.

가장 유용한 것이, 데이터 분석을 위해서 여러 서비스들에 나누어져 있는 데이터들을 한 곳으로 모아 더 빠르고 효율적이게 분석을 수행하고자 할 때이다. 혹은, 다수의 MySQL 서버 데이터를 하나의 MySQL 서버에서 백업하고자 할 때에도 손쉽게 구현할 수 있다.

멀티 소스 레플리카에서는 자신과 연결된 소스 서버들의 이벤트들을 병렬로 동기화 하는데, 이는 개별적인 스레드와 Relay log를 가지기에 가능하다.

참조

Real MySQL 8.0 (1권)
https://dev.mysql.com/doc/refman/5.7/en/group-replication-primary-secondary-replication.html
https://hudi.blog/mysql-replication-topology/
https://www.percona.com/blog/mysql-5-7-multi-source-replication/

0개의 댓글