DB/DB

[테코톡] DB Replication 2

finepiz 2023. 3. 8. 02:15

---

https://youtu.be/NPVJQz_YF2A - 엔지, 자막

https://youtu.be/95bnLnIxyWI - 영이, 자막

https://youtu.be/y42TXZKFfqQ - 히브리 클러스터링 샤딩 레플리케이션

 

---

https://youtu.be/95bnLnIxyWI - 영이, 자막, 2021.10.28

뭔지

왜쓰는지

어떤방식으로 동작하는지

 

---

MySQL Replication 기준으로 진행

 

---

왜써?

데이터베이스의 부하를 줄이기 위해? 그것도 맞아

이용량이 많지 않아도 Replication을 적용하는 경우가 많다. 부하를 줄이는 것 말고 다른 이점이 있다!

4가지의 이점이 있어

 

---

스케일 아웃

 

부하를 줄이기 위해 서버를 늘리는 것

하나의 서버에서 감당하던 쿼리처리를 두개 세개 이상의 서버에서 나눠서 하니 부담이 줄어든다

 

---

데이터 백업

소스서버 하나로만 구성해서 소스서버에서 데이터 백업을 할 경우, 실제 실행중인 쿼리들이 영향을 받을 수 있어

최악의 경우 쿼리의 처리 속도가 느려져 서비스에 문제가 생길 수 있다

복제를 해서 레플리카 서버에서 데이터 백업을 진행할 수 있어

 

---

그렇게 무거운 작업을 소스서버에서 하게되면 실제 서비스에 문제가 될 수 있다

 

---

특정 지역에서만 서비스하는게 아니고, 전 세계적으로 서비스를 제공할 때

DB서버가 멀리 떨어져 있으면 빠른 응답을 받기 힘들어

넷플릭스의 DB서버가 미국에만 있으면, 서비스를 이용하는 한국 고객은 느릴 것

 

멀리 떨어져 있을 수록 애플리케이션 서버와 DB서버의 통신 시간이 더 늘어나

실제 서비스 되는 곳과 가까운 곳에 레플리카를 구성하고 응답 속도를 개선할 수 있다

 

---

Replication은 어떤 원리야?

MySQL에서 Replication을 이해하려면 먼저 바이너리로그를 알아야 한다

모든 변경사항은 아래 세가지

순서대로 저장

 

MySQL의 복제는 이 바이너리 로그를 기반으로 구현된다.

 

---

바이너리 로그 파일 보기

위에건 목록 보기

밑에건 파일명과 위치정보

 

바이너리로그 파일 위치 기반으로 바이너리로그를 식별할 때 사용하는 파일명과 위치

 

---

소스서버에서 생성된 바이너리 로그가 레플리카 서버로 전송되고,

레플리카 서버에서는 해당 내용을 로컬 디스크에 저장한 뒤, 

자신이 가진 데이터에 반영

 

이렇게 소스서버와 레플리카 서버 간에 데이터 동기화가 이뤄짐.

 

이 과정은 MySQL에서 세개의 스레드에 의해 동작

첫번째건 소스서버

둘째 셋째는 레플리카 서버에 존재

 

---

 

---

Binary Log Dump Thread가 보낸 Binary Log Event를 가져와서 로컬 서버의 파일(=Relay Log)로 저장

복제가 시작되면 스레드가 생성

복제가 멈추면 스레드 종료

 

이때 소스서버와 레플리카 서버를 연결할 때 사용하는 정보는 Connection Metadata에 있다

 

Connection Metadata에 대한 정보는 mysql.slave_master_info테이블에 저장됨

버전에 따라 파일로 관리되는 경우도 있는데, MySQL 데이터 디렉토리에 파일 형태로 저장

 

---

Replication I/O Thread에 의해 작성된 Relay Log 파일의 이벤트를 읽고 실행하는 역할

Relay Log에 저장된 소스서버의 이벤트들을 서버에 적용하는 컴포넌트를 Applier라고 한다

 

Applier Metadata는 이벤트가 저장된 릴레이로그 파일명과 파일 내 위치 정보를 담고 있고

이 정보를 바탕으로 레플리카 서버에 이벤트들을 적용한다

 

컴포넌트 Applier는 MySQL DB에 slave_relay_log_info 테이블에 저장된다  ▽그 기본 DB MYSQL말하는거구나? 저기 그림에 mysql.이라고 하는거 보니까

 

---

바이너리 로그에 변경 내역이 있다는 것을 알고 이를 통해 복제가 이뤄진다는 것을 알았다

그럼 바이너리 로그를 어떻게 식별해? 어떻게 변경 내용을 식별하는지?

바이너리 로그 변경 내역을 찾는 방식은 두가지

1)

2)

 

당연히 소스 서버에 바이너리 로그가 활성화 돼 있어야겠지. show master status쳐보면 기록돼있는지 확인할 수 있어

 

---

1)은

이벤트 하나를 소스 서버의 바이너리 로그 파일명과 위치값의 조합으로 식별한다는 뜻

중요한 건 server_id

이벤트 별로 이벤트가 최초로 발생한 MySQL 서버를 식별하기 위해 MySQL 서버의 server_id가 이용

server_id를 지정 안하면 기본값이 1

Replication을 하게 된다면 레플리카 서버에서는 반드시 server_id를 지정해줘야 한다

+Replication에 참여하는 각 서버마다 다른 서버 id로 지정해줘야 한다

 

---

MySQL 5.5버전까지는 1)만 가능, 하지만 식별 과정이 소스서버에서만 유효하다는 단점. 동일한 이벤트가 레플리카 서버에서 동일한 위치와 동일한 파일명으로 저장된다는 보장이 없다. 어떤 경우에는 동일한 이벤트인데 서로 다른 식별값을 가지는 경우가 있을 것.  ▽Replication 1편 보면 왜 문젠지 더 자세히 설명해놨던 것 같아

 

이런 문제점을 해결하기 위해 각 이벤트들이 복제에 참여한 모든 MySQL 서버들에서 동일한 고유식별 값을 가지면 어떨까라는 생각에 2) 로 식별하게 됨

여기까지 식별과정에 따라 달라지는 복제 타입

 

---

바이너리 로그는 어떻게 생겼는지??

Statement : SQL문을 바이너리 로그에 그대로 기록

Row : 변경된 데이터 자체를 기록

Mixed : 혼합

 

---

Statement는 MySQL에 바이너리로그가 처음 도입 됐을 때부터 존재한 포맷

저 격리 수준 이하 방식에서는 하나의 트랜잭션 내에서도 각 쿼리가 실행되는 시점마다 스냅샷이 달라질 수 있는데, 이로 인해 복제시 서버와 레플리카 서버의 데이터가 일치하지 않을 수 있어서 Statement 방식이 허용되지 않음.  ▽언젠가 이해하겠지

 

비확정적이란, delete, update를 order by없이 limit을 사용하게 되면 매번 다른 결과가 나올 수 있는 상황처럼, 결과가 매번 달라질 수 있는 경우를 말함.

 

---

입으로 설명한게 저기 다 써져 있어서 안적음

장점 때문에 가장 안전한 방식

 

Row 포맷으로 넘어오면 어떤 쿼리들이 넘어왔고, 현재 실행중인 쿼리가 어떤 것인지 Replica서버에서는 확인할 수 없다

 

---

두가지 방식의 장단점 보완 Mixed

binlog_format을 MIXED로 지정한다

 

쿼리의 대부분은 Statement포맷으로 기록

실행된 쿼리가 Statement포맷으로 기록돼서 복제됐을 때, 문제가 될 가능성이 있는 안전하지 못한 쿼리라면 Row포맷으로 변환되어 기록된다.

 

---

진짜 데이터를 보내보자!

이때

소스서버가

레플리카 서버에

이벤트들이 잘 보내졌는지 확인하냐, 안하냐에 따라 복제 동기화 방식이 나뉜다

 

MySQL에서는 복제 동기화 방식을 두가지 제공

 

---

소스서버는 알지 못하니까 소스서버에 장애가 발생하면 소스서버에서 최근까지 적용된 트랜잭션이 레플리카 서버로 전송되지 않을 수 있다

 

---

레플리카 서버로부터 확인 응답을 받고 난 후 커밋

그 이후 클라이언트에게 결과를 반환

적어도 하나의 레플리카 서버에 트랜잭션이 전송됐음을 보장

근데 전송이 보장된거지 실제 적용이 보장된 건 아니다

또 서버의 응답을 기다리기 때문에 비동기방식보다 트랜잭션 처리가 느려질 수 있다

반동기 복제에서 응답이 안오면 무기한적으로 기다릴 수 있기 때문에, 소스서버는 지정된 타임아웃 시간동안 응답이 없으면 비동기 복제 방식으로 전환된다

 

---

그래서, 소스 서버와 레플리카 서버 하나씩 두면 돼?? 구성 방식에도 여러가지가 있고 크게 5가지다

 

---

하나의 소스서버에 하나의 레플리카 서버

소스서버에 문제가 생겼을 때 예비 서버데이터 백업 수행을 위한 용도로 많이 사용

 

---

하나의 소스서버에 두개 이상의 레플리카 서버를 연결

하나는 예비

하나는 읽기 요청 처리 분산

 

---

하나의 소스 서버에 연결된 레플리카 서버수가 많다면, 바이너리 로그를 읽고 전달하는 작업 자체가 부하가 될 수 있다. 이때 체인 복제를 사용한다.

 

소스서버가 해야할 바이너리 로그 배포 역할을 새로운 서버로 넘길 수 있다

 

---

두개의 서버가 서로 소스서버이자 레플리카 서버로 구성돼 있는 형태

두 서버 모두 쓰기가 가능하다는 것이 특징

각 서버에서 변경한 데이터는 복제를 통해 다시 각 서버에 적용, 양쪽에서 쓰기가 발생하지만 두 서버는 동일한 데이터

▽Always On도 소스레플리카가 의미가 없었잖아

 

목적에 따라

ACTIVE-PASSIVE  ▽ACTIVE-STANBY랑 같은거겠지?

ACTIVE-ACTIVE

형태로 사용할 수 있다

 

싱글 레플리카와 똑같은 형태라 생각할 수 있지만 한 서버에서 문제가 생겼을 경우 전환을 바로 가져갈 수 있다

 

---

하나의 레플리카 서버가 둘 이상의 소스 서버를 갖는 형태

여러 서버에 존재하는 다른 데이터를 하나의 서버로 통합하거나, 샤딩 돼 있는 테이블 데이터를 하나의 테이블로 통합할 때 사용할 수 있다

 

 

---

직접 설정하는 방법은 버전별로 많은 차이가 있다

 

---