Replication이란?
Replication은 말그대로 복제를 뜻하며 2대 이상의 DBMS를 나눠서 데이터를 저장하는 방식이다.
여기서 2대 이상의 DBMS는 Master / Slave 구성을 해야한다.
👉 요즘은 Slave라고 부르지 않기 때문에 Source서버 / Replica서버로 나눠서 부른다.
위 사진처럼 한 DB서버에서 모든 CRUD처리를 하게 된다면 나중에 사용자가 많아질 때 DB서버 하나가 많은 Query를 처리하기 힘든 상황이 오므로 Replication을 쓰게된다.
따라서 위 사진과 같이 Query의 대부분을 차지하는 Select를 다른 DB서버에 넘겨주는 방식으로 Replication방식이 나오게 되었다.
Replication 서버를 구축하는 목적
1. 스케일 아웃
위에서 설명한 것과 동일하게 하나의 서버에서 감당하던 쿼리 처리를 두 개, 세 개 이상의 서버에서 나눠서 부담을 줄일수 있다.
2. 데이터 백업
Replica를 안하더라도 DB백업은 어차피 해야하는 작업이다.
만약 소스 서버에서 백업을 할경우 실제 실행중인 쿼리들이 영향을 받을 수 있다. 최악의 경우 쿼리 처리가 느려져 서비스에 문제가 생길 수 있다. 이럴 경우 Replica 서버에서 백업시 발생하는 문제들을 해결한다
3. 데이터 분석
분석용 쿼리는 대량의 데이터를 조회하고 쿼리 자체가 무거워져 실제 서비스에 문제가 될 수 있다.
따라서 데이터 분석의 경우에도 Replica서버를 전담서버로 두는 것이 좋다.
4. 데이터의 지리적 분산
대부분의 서비스는 특정 지역에 국한되지 않고 전 세계적으로 서비스를 제공하는데, DB 서버가 멀리 떨어져있게 된다면 그만큼 빠른 응답을 받기 힘들게 된다.
👉 Netflix DB서버가 미국에만 있다면 한국에서 이용하는 고객은 속이 터질것이다. 따라서 빠른 응답을 위해 애플리케이션 서버에 가까운 곳에 Replica서버를 구성할 수 있다.
바이너리 로그란?
MySQL서버에서 발생하는 모든 변경사항을 별도의 로그 파일에 순서대로 저장하는 것을 의미한다.
소스서버에서 생성된 바이너리 로그를 레플리카 서버로 전송하고 레플리카 서버에서 해당 내용을 로컬 디스크에 저장한 후, 데이터에 반영함으로써 소스서버와 레플리카 서버간에 데이터 동기화가 이루어진다.
위 과정에는 MySQL에서 3개의 스레드에 의해 동작된다.
먼저,Binary Log Dup Thread는 소스서버에서,
Replication I/O Thread,Replication SQL Thread는 레플리카 서버에 존재한다.
Binary Log Dup Thread는 바이너리 로그를 레플리카 서버로 전송하는 역할을 한다.
레플리카 서버가 소스서버에 연결되면 소스서버에서 내부적으로 Binary Log Dump Thread를 생성하게 된다.
Replication I/O Thread는 Binary Log Dup Thread가 보낸 바이너리 로그 이벤트를 가져와 로컬 서버의 파일로 저장하는 역할이다. 복제가 시작되면 스레드가 생성되고 복제가 멈추면 스레드는 종료된다. 이때 소스서버와 레플리카 서버를 연결할 때 사용하는 정보는 Connection Metadata에 있으며 커넥션 메타데이터에 대한 정보는 MySQL 데이터베이스 slave_master_info 테이블에 저장된다. 버전에 따라 파일로 관리되는 경우도 있는데 파일로 관리되는 경우 MySQL 데이터 디렉토리에 파일 형태로 저장된다.
Replication SQL Thrad는 위의 I/O Thread에 의해 작성된 릴레이로그 파일의 이벤트를 읽고 실행하는 역할이다.
릴레이로그에 저장된 소스서버의 이벤트들을 서버에 적용하는 컴포넌트를 어플라이어라고 하는데 어플라이어 메타 데이터는 이벤트가 저장된 릴레이로그 파일 명과 파일 내 위치 정보를 담고 있으며 이 정보를 바탕으로 레플리카 서버에 이벤트들을 적용한다. 컴포넌트 어플라이어는 MySQL 데이터베이스에 slave_relay_log_info 테이블에 저장된다.
"바이너리 로그에 변경 내역이 있는것을 알고 이를 통해 복제가 이루어진다"
그렇다면 변경 내용 식별은 어떻게 이루어지는가?
1. 바이너리 로그 파일 위치 기반
이벤트 하나를 소스서버의 바이너리 로그 파일명과 위치 값의 조합으로 식별
이때 MySQL서버의 server_id를 이용하게 된다.
레플리케이션에 참여하는 각 서버마다 다른 서버 id를 지정해 주어야한다.
2. 글로벌 트랜잭션 ID 기반(GTID)
바이너리 로그 파일 기반 복제는 식별 과정이 소스서버에서만 유효하다는 단점이 있다.
동일한 이벤트가 레플리카 서버에서 동일한 위치와 동일한 파일명으로 저장된다는 보장이 없다.
즉, 동일한 이벤트인데 서로 다른 식별값을 가지는 경우가 있을 것이다.
이러한 문제점을 해결하기 위해 각 이벤트들이 복제에 참여한 모든 MySQL 서버들에서 동일한 고유식별 값을 가지면
어떨까라는 생각으로 GTID 글로벌 트랜잭션 id로 식별하게 되었다.
최근 프로젝트에서 나는 AWS RDS를 읽기전용 방식으로 생성하여 GTID방식을 기반으로 사용했다
# 공식문서 #
AWS -> https://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/USER_MySQL.Replication.html
MySQL -> https://dev.mysql.com/doc/refman/5.7/en/replication-gtids.html
바이너리 로그 형태
1. statement 방식SQL문을 바이너리 로그에 그대로 기록하는 방식
주의할 점은 트랜잭션의 격리 수준이 Repeatable Read이상이여야 한다.
이 방식은 delete나 update를 order by 없이 limit을 사용하게 되면 매번 다른 결과가 나올 수 있는 상황처럼 소스서버와 레플리카 서버의 데이터가 일치하지 않을 수 있다.
2. Row 방식
데이터 변경이 발생했을때 변경된 값 자체가 바이너리 로그에 기록되는 방식 (MySQL 5.7.7 버전부터 바이너리 로그의 기본포맷)
어떤 형태의 쿼리든지 복제시 소스서버와 레플리카 서버의 데이터를 일관되게 하는 가장 안전한 방식
하지만 변경 데이터가 전부 기록되기 때문에 단시간에 로그 파일이 커질 수 있다는 문제점이 있다.
-> Row포맷으로 넘어오면 어떤 쿼리들이 넘어왔고 현재 실행중인 쿼리가 어떤 것인지 레플리카 서버에서는 확인이 불가능
3. Mixed 방식
쿼리의 대부분은 Statement 포맷으로 기록될 가능성이 높은데, 만약 실행된 쿼리가 Statement 포맷으로 기록되어 복제됐을 때 문제가 될 가능성이 있는 안전하지 못한 쿼리라면 Row포맷으로 변환되어 기록한다.(위의 두 방식의 장단점을 서로 보완하기 위해 혼합하여 사용)
binlog_format을 MIXED로 지정하여 사용한다.
Replication 동기화 방식
MySQL에서는 복제 동기화에 대해 비동기 복제와 반동기 복제, 두가지 방식을 제공한다.
1. 비동기 복제
비동기 복제는 소스서버가 레플리카 서버에서 변경 이벤트가 정상적으로 전달되어 적용됐는지 확인하지 않는다. 결국 소스서버는 레플리카 서버에 적용이 잘되었는지 알지 못하게되고 소스 서버에 장애가 발생하면 소스 서버에서 최근까지 적용된 트랜잭션이 레플리카 서버로 전송되지 않을 수 있다.
2. 반동기 복제
반동기 복제는 레플리카 서버로 부터 확인 응답을 받고 난 후 커밋하게되고 그 이후 클라이먼트에게 결과를 반환하게 된다. 적어도 하나의 레플리카 서버에 트랜잭션이 전송되었음을 보장하게 된다. 하지만 전송이 보장된 것이지 실제로 적용이 보장되는 것은 아니다. 또한 서버의 응답을 기다리기 때문에 비동기 방식보다 트랜잭션 처리가 느려질 수 있다. 반동기 복제에서 응답이 안오면 무기한적으로 기다릴 수 있기때문에 소스서버는 지정된 타임아수 시간동안 응답이 없는 경우 비동기 복제 방식으로 전환된다.
Replication 사용시 주의사항
1. 호환성을 위해 ****Replication을**** 사용하는 MySQL의 버전을 동일하게 맞추는 것이 좋다.
2. Replication을 사용할때 MySQL 버전이 다른 경우 레플리카 서버가 상위버전 이여야 한다.
3. Replication을 가동시 소스서버, 레플리카 서버 순으로 가동시켜야한다.
소스 , 레플리카 서버 구성방식
1. 싱글 레플리카 복제
싱글 레플리카 복제는 하나의 소스서버에 하나의 레플리카 서버만 연결되어 있는 복제 형태이다. 이경우 주로 소스서버에 문제가 생겼을 때 예비 서버 및 데이터 백업 수행을 위한 용도로 많이 사용된다.
2. 멀티 레플리카 복제
멀티 레플리카 복제는 하나의 소스서버에 2개 이상의 레플리카 서버를 연결한 복제 형태이다. 여기에서도 하나의 서버는 예비용으로 구성하고 다른 서버를 읽기 요청 처리를 분산하는 용도로 사용한다.
3. 체인 복제
체인 복제는 하나의 소스서버에 연결된 레플리카 서버수가 많다면 바이너리 로그를 읽고 전달하는 작업 자체가 부하가 될 수 있는데 이때 사용하는 방식이다. 소스서버가 해야할 바이너리 배포 역할을 새로운 서버로 넘길 수 있다.
4. 듀얼 소스 복제
듀얼 소스복제는 두개의 소스서버가 서로 소스서버이자 레플리카 서버로 구성되어 있는 형태이다. 두 서버 모두 쓰기가 가능하다는 것이 특징이며 각 서버에서 변경한 데이터는 복제를 통해 다시 각 서버에 적용되므로 양쪽에서 쓰기가 발생하지만 두 서버는 서로 동일한 데이터를 갖게 된다. 목적에 따라 ACTIVE-PASSIVE형태 ACTIVE-ACTIVE형태로 사용될 수 있다. 싱글 Slave와 같은 형태라 생각할 수 있지만 한 서버에 문제가 생겼을 경우 전환을 바로 가져갈 수 있다는 장점이 있다.
5. 멀티 소스 복제
멀티 소스복제는 하나의 레플리카 서버가 둘 이상의 소스서버를 갖는 형태를 말한다. 여러 서버에 존재하는 다른 데이터를 하나의 서버로 통합하거나, 샤딩되어있는 테이블 데이터를 하나의 테이블로 통합할 때 사용할 수 있다.
AWS RDS에서 replica서버 생성
위 처럼 읽기 전용 복제본으로 생성하면 Replica DB서버를 구축할 수 있다.
'지식 저장소' 카테고리의 다른 글
MPA와 SPA란? (0) | 2023.05.11 |
---|---|
같은 값 기준 정렬 후 페이징 시 목록 꼬임 문제 (0) | 2023.01.10 |
Cannot add or update a child row 에러 (0) | 2022.01.19 |
빌더 패턴(Builder Pattern) 을 사용하는 이유 (0) | 2021.12.30 |
REST방식 , JSON , AJAX 의미 (0) | 2021.12.28 |