[DB]Mysql Replication

배상규·2023년 10월 24일
1
post-thumbnail

프로젝트를 진행하면서 고가용성과 성능향상을 위해 DB를 이중화하기로 하였고, 이를 Replication을 사용하기로 결정했습니다!

DB Replication 이란?

그렇담 이 Replication은 무엇인가?!

데이터베이스를 복제하는 행위

그렇담 왜 하나의 DB를 사용하면 되지만 여러개의 DB를 사용할까?

Case 1
DB의 이상으로 요청에대한 응답이 되지 않았을때
Case 2
요청 트래픽의 증가로 인한 트래픽의 부하 분산이 필요한 상황 일때
이때 스케일업을 통해 어느정도 보완이 가능하겠으나, 스케일업에는 분명 한계가 있습니다!

이러한 상황을 타개하기 위해서 DB Replication을 사용해야 합니다.


DB Replication의 구조

일단 원본 데이터를 가진 데이터베이스 서버를 소스서버 복제된 DB의 데이터를 가지고 있는 DB 서버를 레플리카 서버 라고 합니다.

소스 서버에서 변경이 일어나면 변경된 내용은 레플리카 서버에 동일하게 반영이 됩니다. 이런 구조를 소스-레플리카 구조라고 합니다!

그렇기 때문에 앞선 Case 1의 경우 레플리카 서버를 소스서버로 승격시켜 사용할 수 있습니다.
Case2의 경우는 소스 서버를 쓰기 전용 DB, 레플리카 서버를 읽기 전용 DB로 사용해 부하를 해결할 수 있습니다.


복제는 어떻게 발생 하는가?

그렇담 이러한 레플리카에 데이터 복제는 어떻게 가능하게 하는지 알아보도록 합시다.

바이너리 로그 기반 복제

바이너리 로그란?

모든 변경사항이 로그 파일에 순서대로 기록되는 것을 의미합니다.

즉 소스서버에 변경이 발생되어 바이너리 로그 이벤트가 기록이 되면 이 이벤트는 레플리카 서버가 자신의 로컬 디스크에 저장한 이후 이벤트를 읽어 들여 레플리카DB 자기자신의 데이터 파일에 반영합니다.

좀더 자세히 알아볼까요?

일단 복제 쓰레드는 총 세 가지 쓰레드가 사용됩니다.
이벤트 순서 대로
1. 소스서버의 바이너리 로그에 이벤트가 발생되면 바이너리 로그 덤프 쓰레드가 이 이벤트를 읽어 레플리카 서버로 전송합니다.
2. 레플리카 서버의 I/O 쓰레드는 이 변경 이벤트를 자신의 로컬파일인 릴레이 로그에 저장합니다.
(이때 아직 자신의 DB엔 변경이 일어나지 않습니다.)
3. 레플리카 서버의 DB 변경을 위해 SQL 쓰레드가 변경 내용을 데이터 파일에 저장합니다.

레플리카는 소스서버의 바이너리 로그 이벤트를 식별하여 반영할까?

이 방식에는 두 가지 방식이 있습니다.

1. 바이너리 로그 파일 위치 기반 복제

  • 이 방식의 경우 소스서버 바이너리 로그의 로그 파일명과 오프셋을 이용해 식별합니다.
  • ex) Binary-log.00002:110 이라는 로그가 있다고 한다면 Binary-log는 로그파일명이며 콜론뒤 110은 Offset입니다.
  • 이러한 방식의 단점은 소스서버에만 유용한 식별 방법 이라는 단점이 있습니다.
  • 즉 소스서버에 문제가 생겨 다른 레플리카 서버가 소스서버로 승격된 경우 다른 레플리카 서버들(복제에 참여하는)은 다시 이 바이너리 파일의 위치를 찾아야 하기 때문에 복구에 시간이 소요 됩니다.

즉 동일한 이벤트가 레플리카 서버에서도 동일한 파일명의
동일한 위치에 저장된다는 보장이 없습니다.

2. 글로벌 트랜잭션 아이디(GTID)

앞선 단점을 해결하기 위해 MySQL 5.6 버전 부터는 글로벌 트랜잭션 기반 복제를 기본 복제 방식으로 사용하고 있습니다.

그렇담 이 글로벌 트랜잭션 아이디는 무엇일까?

복제에 참여한 모든 데이터베이스들이 고유한 식별값을 가지며 이 값들은 모두 동일하기 때문에 동일한 이벤트에 대해서 동일한 글로벌 트랜잭션만 읽기만 하면 반영이 가능하게 됩니다.


복제 데이터 포맷

바이너리 로그 포맷

1. Statement 기반 방식

INSERT INTO member VALUES(1,'TESTNAME')

이러한 SQL문이 일어나면 이 SQL문이 바이너리 로그에 그대로 저장되는 방식을 Statement 기반 방식이라고 합니다.

  • 장점: 으로는 여러 개의 데이터를 수정하는 쿼리여도 바이너리 로그에 SQL문 딱 하나만 저장되기 때문에 저장 공간에 대한 부담이 감소 되며, 빠른처리가 가능하게 됩니다.
  • 단점 :하지만 실행하는 쿼리마다 결과값이 바꾸니는 경우 데이터 동기화 문제가 발생하며 트랜잭션 격리수준이 REPEATABLE-READ 이상에서만 사용이 가능하다는 단점이 있습니다.

일관되지 않은 데이터가 저장될 위험이 있습니다!

2. Row 기반 방식

앞선 Statement 기반의 단점을 보완하여 MySQL 5.7.7 버전 부터는 이 Row 기반 바이너리 로그 포맷을 기본으로 사용합니다.

이 방식은 변경 값 자체가 바이너리 로그에 그대로 저장되어 있는 형식을 말합니다.

  • 장점 : 모든 트랜잭션 격리 수준에서 사용 가능 하다.
  • 단점 : 데이터를 변경하는 SQL문이 많이 발생되면 바이너리 로그 파일의 크기가 너무 커질 수 있으며, SQL쿼리를 육안으로 확인하기 어렵습니다.

    그럼에도 불구하고 데이터를 일관되게 저장 하는 가장 안전한 방식 입니다.

3. Mixed 기반 방식

이 Mixed 방식은 사용자가 커스텀하여 사용이 가능합니다.
기본적인 쿼리는 Statement 포맷으로 저장하되 비확정적 쿼리 라면 Row 포맷으로 저장하는 방식을 사용할 수 있습니다.


복제 동기화 방식

그렇다면 복제가 잘 일어났는지 어떻게 확인할까?

1. 비동기 복제

소스 서버가 레플리카 서버에서 변경 이벤트가 정상적으로 전달 됐는지 확인하지 않는다.

자세히 알아보자면.

  1. 데이터 변경 요청이 들어온다면 바이너리 로그의 이벤트를 먼저 작성한 뒤 바로 소스 서버 스토리지 엔진에 커밋을 하게 된다.
  2. 그 이후 변경 이벤트를 레플리카 서버로 전송합니다.

이 방식은 변경 이벤트를 레플리카 서버로부터 소스 서버로 확인 이벤트를 보내지 않습니다. 그렇기 때문에 성능은 빠를 수 있으나 동기화는 보장하지 않습니다.

2. 반동기 복제

앞선 비동기 복제의 단점을 보완하여 MySQL 5.5 버전 부터는 반동기 복제 방식을 사용합니다.

소스 서버는 레플리카 서버가 소스 서버로부터 전달 받은 변경 이벤트를 릴레이 로그에 기록 후 응답을 보내면 그때 트랜잭션을 완전히 커밋한다.

자세히 알아보자면

  1. 데이터 변경 요청이 소스 서버로 들어오면 바로 이벤트를 바이너리 로그에 기록후 레플리카 서버로 전송합니다.
  2. 레플리카 서버는 이 변경 이벤트를 잘 받았다는 응답을 보내게 되며, 응답이 오고 난 이후 소스 서버는 변경 내역을 스토리지 엔진에 커밋합니다.

이때 레플리카 서버가 보내는 응답은 변경 이벤트를 잘 받았다는 응답일뿐 이벤트가 레플리카 서버에 적용되었다는 응답을 보내는 것은 아닙니다.


복제 구성 형태(복제 토폴리지)

그렇다면 소스 서버와 레플리카 서버를 구성 할까요?

1.싱글 레플리카

이는 소스 서버와 레플리카 서버를 한대씩 두는 방식이며, 레플리카 서버는 예비 서버 및 데이터 백업용으로 활용합니다.

2.멀티 레플리카

싱글 레플리카 방식에서 레플리카 서버를 한대 더 둔 멀티 레플리카 방식이 있으며 이때 레플리카 두 대를 사용하는데 한대는 쿼리 부하 분산용으로, 두 번째 레플리카 서버는 백업 용으로 사용할 수 있습니다.

3. 체인 복제

소스 서버에 연결된 레플리카 서버가 많다면 소스 서버의 복제부하가 커지게 됩니다. 이때 다른 레플리카 서버를 소스 서버로 활용하여 복제 부하를 분산시키는데 사용할 수 있습니다.
혹은 기존에 사용하던 서버를 업데이트 하거나 장비 교체할 때 사용할 수 있습니다.

4. 듀얼 소스 복제

싱글 레플리카를 두개 만들어 놓은 것이며 이는 두 서버 모두 쓰기가 가능한 형태입니다. 이방식은 트랜잭션이 충돌이 일어날 경우 복제 멈춤 현상이 일어나기 때문에 잘 사용되지 않습니다.

5. 멀티 소스 복제

하나의 레플리카 서버가 둘 이상의 소스서버를 가지며 이는 데이터를 분석 시 데이터를 모아 분석을 수행할 때 사용하게 됩니다.


장애복구

그렇다면 소스 서버에 장애가 난 경우엔 레플리카 서버를 활용하는 경우들은 살펴 보았습니다. 하지만 레플리카 서버에 문제가 생긴다면 어떻게 다시 동기화를 만들까?

1. 크레시 세이프

MySQL에선 크레시 세이프 복제 방식을 제공하고 있습니다.

  1. 레플리카 서버는 I/O 쓰레드와 SQL 쓰레드를 이용하여 소스 서버에 바이너리 로그 이벤트 위치를 읽을 때와 트랜잭션 실행정보를 읽을 때 어디까지 읽었는지에 대한 포지션 정보를 로컬에 저장해 둡니다.
  2. 레플리카 서버에 문제가 생겨 다시 재가동했을 시 그 정보를 기반으로 다시 소스서버에 동기화 과정을 거칩니다!
profile
기록에 성장을

0개의 댓글