DB Replication(레플리케이션)이란?
Replication이란 번역하면 ‘복제’라는 뜻으로 DB를 복제한다는 뜻이다.
기준이 되는 서버를 Source(원본) 서버라 하고, Source 서버와 동일한 내용을 갖는 또 다른 서버를 Replica(복제본)라 한다.
즉, DB를 복제해서 여러 대의 DB 서버에 저장하는 방식이다.
위는 Replication 기본 형태로 Source는 쓰기 작업만, Replica는 읽기 작업만 수행하도록 구성한다.
(이외에도 다양한 Replication 방식이 있는데 ‘MySQL Replication 구성 형태’ 목차에서 설명한다.)
- 참고로 기존에는 Master/Slave라는 용어를 사용해왔지만 위키백과에서 다음과 같은 문제로 Source/Replica와 같은 용어가 채택되고 있다고 한다.
DB Replication은 왜 필요한가?
위와 같은 구조로 T1 Shop이 설계되어 있다고 가정해보자.
2024-11-02 일 T1이 Worlds 결승전에 이겨 우승이 확정되었다.
환호하는 팬들로 T1 Shop에 굿즈를 구매하기 위한 수 많은 트래픽이 몰렸다.
수 많은 트래픽에 대해서는 로드 밸런서와 오토 스케일링으로 서버에 대한 부하 줄이고 가용성을 확보하긴 했다.
이 수많은 트래픽에 대한 데이터를 처리하기 위한 DB는 하나로 이 부하를 견디지 못하고 결국 장애가 발생하고 말 것이다.
이는 곧 DB 병목 현상으로 인해 T1 Shop 전체의 장애로 이어 지게 된다.
이러한 예측 불가능한 트래픽 급증 상황에서 DBMS의 안정성과 가용성을 보장하기 위해
DB Replication를 적용하여 SPOF(Single Point Of Failure)를 해결하고 다음과 같은 이점을 챙길 수 있다.
- 쓰기와 읽기 작업을 담당하는 DB를 분리하여 작업 분산 처리, 트래픽 증가 시 추가로 복제하여 부하 분산
- 원본 DB 장애 시 복제 DB를 원본 DB로 승격하여 고가용성 확보
MySQL Replication 작동 방식
그렇다면 MySQL에서는 어떻게 복제가 일어날까?
다음과 같이 Binary Log 방식으로 복제가 일어난다.
(Binary Log : MySQL 서버에서 발생하는 모든 데이터 변경사항을 시간 순서대로 기록하는 로그 파일)
- 원본 DB에 뭔가 바뀜
- 바뀐 것을 Binary Log에 기록
- Binary Log를 복제 DB에 전달
- 복제 DB가 Binary Log를 읽어 데이터 파일에 저장
내부 동작 방식을 좀 더 자세히 보면 다음과 같다.
복제 변경 내역을 어떻게 식별해 반영할까?
MySQL의 레플리케이션은 바이너리 로그에 기록된 변경 내역들을 식별하는 방식에 따라 다음과 같이 2가지로 나뉜다.
바이너리 로그 파일 위치 기반 복제
Source Binary Log 파일명과 offset(로그 파일 내에서 변경을 수행할 위치)를 통해 변경 내역을 식별하는 방법이다.
하지만 이 방식은 문제점이 있다.
아래 그림을 통해 한번 살펴보자.
현재 A, B Replica가 있고 Replica B는 복제 지연으로 offset이 다르다.
만약 이 상황에서 Source의 장애로 Replica A가 Source로 승격됬을 때 어떤일이 발생할까?
Replica A는 복제 지연없이 데이터가 다 반영되었고 Relay Log는 정리되어 비어져있다.
그런데 Replica A가 승격이 되면 Replica B는 120 ~ 180 사이의 데이터를 동기화해야하는데
새로 승격된 Source에는 이 정보가 없어 동기화가 불가능해 진다.
GTID (Global Transaction ID) 글로벌 트랜잭션 ID 기반 복제
Replication에 참여한 Replica들이 변경 사항에 대해 동일한 식별자를 가지도록 하는 방식이다.
MySQL 5.6버전 부터 등장한 타입으로 기본 복제 타입으로 사용한다고 한다.
위와 같은 문제 상황에서도 변경 사항을 고유 식별자인 GTID로 식별 가능하므로
새로운 Source로 부터 Replica가 동기화를 수행할 수 있다.
Binary Log 형식
Binary Log 파일안에 있는 로그들은 어떠한 형식으로 저장되어 있을까?
다음과 같이 3가지 형식이 존재한다.
-- 글로벌 설정
mysql> SET GLOBAL binlog_format = 'STATEMENT';
mysql> SET GLOBAL binlog_format = 'ROW';
mysql> SET GLOBAL binlog_format = 'MIXED';
-- 세션 설정
mysql> SET SESSION binlog_format = 'STATEMENT';
mysql> SET SESSION binlog_format = 'ROW';
mysql> SET SESSION binlog_format = 'MIXED';
각 형식별로 어떠한 특징들이 있는지 알아보자.
STATEMENT 기반 포맷
실행된 SQL문을 문장 그대로 기록한다.
INSERT INTO member (name, city) VALUES ('kaki', '김해시');
UPDATE member SET city = '서울시' WHERE name = 'kaki';
DELETE FROM member WHERE name = 'kaki';
SQL문 자체를 저장하기 때문에 1000개 행이 변경되어도 SQL문 크기는 동일하여 저장 공간에 대한 부담이 적다.
반면, 비결정적 프로시저(CURRENT_TIMESTAMP(), RAND()) 사용 시
Source와 Replica의 데이터 불일치 문제가 발생할 수 있다.
ROW 기반 포맷 (기본 값)
변경된 행 데이터를 모두 기록한다.
-- 예시 : UPDATE member SET city = '서울시' WHERE name = 'kaki';
이전 값: id = 1, name = 'kaki', status = '김해시'
새 값 : id = 1, name = 'kaki', status = '서울시'
실제 변경된 데이터 자체를 기록해 Replica는 단순히 데이터만 복사하여 데이터 정합성이 보장된다.
반면, 1000개 행이 변경되었다면 이 모든 데이터들의 변경 전 후가 저장되어 저장 공간을 많이 사용하게 된다.
그럼에도 데이터 정합성을 보장한다는 측면에서 기본 값으로 설정된 것이라 생각한다.
MIXED 기반 포맷
상황에 따라 STATEMENT와 ROW 포맷 자동 선택하는 형식이다.
기본적으로 STATEMENT 포맷 사용하면서
특정 상황(비결정적 프로시저 사용, AUTO INCREMENT 관련 등)에서 자동으로 ROW 포맷으로 전환한다.
이 외에도 아래 공식문서에 따라 MySQL이 안전한 복제를 위해 자동 결정한다.
https://dev.mysql.com/doc/refman/8.4/en/binary-log-mixed.html
이 방법은 자동 최적화가 가능하다는 점과 유연하다는 장점이 있지만
전환 시점을 예측하기 어렵다는 단점이 있다.
MySQL Replication 동기화 방식 (비동기, 반동기)
비동기 복제
Source가 Replica에 변경 사항이 정상적으로 전달되었는지 응답을 기다리지 않고 클라이언트에게 응답하는 방식이다.
빠른 응답이 중요하고 약간의 데이터 지연 허용 가능하다면 고려할 수 있는 동기화 방식.
Source: "트랜잭션 처리 완료했고~ Binary Log 기록도 완료~, 클라이언트야 응답받아"
Client: "감사합니다!"
Source: "Replica야 Binary Log 줄게 알아서 데이터 복사해~"
Replica: "넵! 나중에 할게요~"
장점
- Source가 Replica 응답을 기다리지 않고 클라이언트에 바로 응답을 함으로써 실시간 처리 속도가 빠르다.
- 빠른 트랜잭션 해제로 효율적인 트랜잭션 관리 가능
- Replica의 장애가 Source에 영향을 끼치지 않는다.
단점
- Replica 서버로 이벤트가 제대로 전달됐는지 알 수 없어 데이터 정합성을 보장할 수 없다.
- 변경 전 내용이 조회될 수 있다는 문제가 있다.
반동기 복제
Source의 변경 사항을 Replica가 Relay Log에 기록 후 응답할 때 가지 기다린 후 클라이언트에게 응답하는 방식이다.
응답이 느릴 순 있지만 데이터 정합성이 중요할 때 고려할 수 있는 동기화 방식.
Source: "트랜잭션 처리 완료했고~ Binary Log 기록도 완료~, Replica야 잘 받았으면 응답해줘"
Replica: "네! 받았어요!"
Source: "굿! 이제 Client한테 클라이언트야 응답받아~"
Client: "감사합니다!"
장점
- Replica의 응답을 기다려 좀 더 향상된 데이터 정합성을 보장할 수 있다.
- Source 장애 시 Replica를 Source로 승격 시켜도 문제가 발생하지 않는다.
단점
- Replica의 응답을 기다리기 때문에 트랜잭션 시간이 길어진다.
- Source가 Replica로 부터 응답을 받는 네트워크 통신이 한번 더 발생한다.
반동기식은 Replica에 변경 이벤트를 전달 후 Relay Log에 기록 했다는 응답을 기다릴 뿐
Replica가 변경사항을 반영했음에 대한 응답을 기다리진 않는다고 한다.
또한 Source는 타임아웃을 지정해 Replica의 무한정 기다리지 않고 타임아웃 시간동안 응답이 오지 않으면
자동으로 비동기 복제 방식으로 전환한다고 한다.
이런 이유로 동기가 아닌 반동기라고 하는 것 같다.
MySQL Replication 구성 형태
Single Replication (단일 Source, 단일 Replica)
도입부에 설명한 기본 형태로 구성이 단순하고 관리가 쉽다.
하지만 하나의 Replica만 존재해 고가용성을 보장하긴 힘들고 읽기 분산이 제한적이다.
이는 보통 소규모 서비스나 백업이 목적일 때 구성하는 형태이다.
Multiple Replication (단일 Source, 다중 Replica)
여러 Replica를 둠으로써 읽기 작업 분산해 읽기 작업에 대해 고가용성을 챙길 수 있다.
특정 Replica를 백업용으로 사용할 수도 있다.
Chain Replication (체인 복제)
Source에 연결된 Replica가 Source의 Binary Log를 다시 다른 Replica에 배포하는 순차적으로 복제하는 방식으로
Source 부하 분산 목적으로 사용된다.
이때, Source 1과 그 Replica A를 묶어 1차 복제 그룹이라고 하고
Source 2와 그 레플리카 (Replica A-A, Replica A-B)를 묶어 2차 복제 그룹이라고 한다.
1차 복제 그룹의 Source 2는 Source 1으로부터 직접 복제받기 때문에 빠르게 동기화를 수행할 수 있다.
반면 2차 복제 그룹은 중간 경유로 인한 지연으로 데이터 분석, 단계별 백업 등의 용도로 사용한다고 한다.
Dual Source Replication (이중 Source 복제)
두 서버 모두 쓰기 / 읽기가 가능한 Source 이자 Replica로 서로 동일한 데이터를 갖고 있다.
Active - Active 또는 Active - Passive로 구성할 수 있는데
Active - Active의 경우 리전 별로 쓰기 처리할 Source를 달리 하여 지리적 분산 이점이 있다.
하지만 동시 쓰기 작업 시 두 트랜잭션이 충돌날 수 있는 문제점가 있어 주의해 처리 해야한다.
Active - Passive이 경우에는 Actvie만 쓰기 작업에 사용하고 Passive는 장애에 대비하므로 충돌 위험이 없다.
하지만 Passive의 유휴 상태가 길어질 수록 오히려 리소스 낭비로 이어질 수 있을 것 같다.
Multi Source Replication (다중 Source 복제)
하나의 레플리카 서버가 다수의 소스 서버를 갖는다.
중앙 집중식 데이터 관리로 서로 다른 데이터를 한 곳에 모아 백업해 통합 분석을 할 때 유용하게 사용될 수 있다.
출처
- https://www.youtube.com/watch?v=P7LqaEO-nGU
- https://www.youtube.com/watch?v=NPVJQz_YF2A
- http://cloudrain21.com/mysql-replication
- https://hudi.blog/mysql-replication-synchronous-type/
- https://hudi.blog/mysql-8.0-replication-architecture-and-replication-type/
- https://hudi.blog/mysql-replication-topology/
'◼ DB' 카테고리의 다른 글
[DB] 파티셔닝과 샤딩? 쉽게 알아가보자 (1) | 2024.11.11 |
---|---|
[Redis] 캐싱(caching) 설계 전략에 대해 알아보자 (+TTL 설정 주의점) (0) | 2024.11.10 |
MySQL에 나노초가 이상하게 저장되네? 발생할 수 있는 나노초 관련 이슈를 알아보자. (1) | 2024.10.20 |
[데이터베이스/JPA] 낙관적 락, 비관적 락이란? 예시를 통해 쉽게 알아보자 (5) | 2024.08.27 |
B-Tree란? 구조와 연산 과정을 살펴보자 (1) | 2024.08.26 |