사용자가 지속적으로 증가하면 많은 양의 트래픽이 발생한다. 그러므로 하나의 DB서버로 쓰기와 읽기 작업이 모두 진행된다면 쉽게 DB서버에 부하가 발생할 수 있다.
이 문제에 대한 해결책으로 Master Server 이외에도 추가적으로 Replication된 Slave Server를 두고 읽기 작업(read_only)은 Slave Server로 향하게 함으로서 트래픽이 분산되어 DB서버의 부하를 막을수 있다.
또한 Master Server로 단일 서버일 때 부하로 인해 MYSQL서버가 죽어 서비스를 중단시키는 문제를 사전에 방지할 수 있다.
우선 MYSQL Replication에 대해서 먼저 알아보자
➡️MYSQL Replication
- MYSQL Replication은 2대 이상의 MYSQL 서버가 동일한 데이터를 담도록 실시간으로 동기화 하는 기술이다.
- Replication은 INSERT나 DELETE와 같은 쿼리를 사용해 데이터를 변경할 수 있는 서버와 SELECT쿼리로 데이터를 읽기만 할 수 있는 서버로 나뉜다.
- MYSQL에서는 쓰기와 읽기 역할로 구분해, 쓰기를 master server 읽기를 slave server라고 한다.
- MYSQL Replication에서 master server는 반드시 1개이고 slave server는 1개 이상으로 구성될 수 있다.
📁master server
- MYSQL의 바이너리 로그가 활성화되면 어떤 MYSQL 서버든지 master server가 될수 있다.
- 애플리케이션 입장에서 보면 master서버는 데이터가 생성,변경,삭제되는 시작점이라고 볼 수 있다.
- Replication에 참여하는 서버들중에 변경이 허용되는 서버는 Replication되는 데이터의 일관성을 보장하기 위해 master server로 한정되는 경우가 많다.
- slave server에서 변경된 데이터를 요청하면 master server는 그 바이너리 로그를 읽어 slave server로 넘긴다.
- slave server에서 변경된 데이터를 요청하면 데이터를 slave server로 넘기는 역할은 master server 장비중에 dump thread가 전담한다.
📁slave server
- master server가 바이너리 로그를 가지고 있다면 slave server는 릴레이 로그를 가지고 있다.slave server의 I/O 스레드는 master server에 접속해 변경 내역을 요청하고 받아 온 변경 내역을 릴레이 로그에 기록한다.
- 데이터를 받아 올 마스터 장비의 정보(IP주소와 포트번호, 접속계정)를 가지고 있는 경우 slave server가 된다.
- slave server의 SQL 스레드가 릴레이 로그에 기록된 변경 내역을 재실행함으로써 슬레이브의 데이터를 마스터와 동일한 상태로 유지한다.
- I/O스레드와 SQL스레드는 master server에서는 가동되지 않으며, 복제가 설정된 slave server에서 자동으로 가동하는 스레드이다.
💡Replication할때 주의할 점
- slave server는 하나의 master server만 설정이 가능하다.
- 마스터와 Slave Server의 데이터 동기화를 위해 Slave Server는 읽기 전용으로 설정한다.
- Slave Server용 장비와 마스터와 동일한 사양이 좋다.
- 여러 개의 스레드로 실행된 쿼리가 Slave Server에서 지연되지 않고 하나의 스레드로 처리될 수 있다.
- 데이터 변경은 데이터 조회보다는 10프로 수준으로 유지되는것이 일반적이기 때문에 master server와 Slave Server를 같은 사양으로 유지할 때가 많다.
- Slave Server는 master server가 다운된 경우 그에 대한 복구 대안으로 사용될 때도 많기 때문에 사양을 동일하게 맞추는 경우가 대부분이다.
- Replication이 불필요한 경우 바이너리 로그를 중지한다.
- 바이너리 로그를 안정적으로 기록하기 위해 갭 락(Gap lock)을 유지하고, 매번 트랜잭션 이 커밋될 때 마다 데이터를 변경시킨 쿼리 문장을 바이너리 로그에 기록해야 한다. 바이너리 로그를 기록하는 작업은 AutoCommit이 활성화 된 MySQL 서버에서 심각한 부하로 나타날 때가 많다.
- 바이너리 로그를 안정적으로 기록하기 위해 갭 락(Gap lock)을 유지하고, 매번 트랜잭션 이 커밋될 때 마다 데이터를 변경시킨 쿼리 문장을 바이너리 로그에 기록해야 한다. 바이너리 로그를 기록하는 작업은 AutoCommit이 활성화 된 MySQL 서버에서 심각한 부하로 나타날 때가 많다.
- 바이너이 로그와 트랜잭션 격리 수준
- 바이너리 로그 파일릉 어떤 내용이 기록되느냐에 따라 statement 포맷 방식과 row포맷 방식이 있다. row포맷 방식은 master server에서 실행된 쿼리에 의해 코드 값을 기록하는 방식이고, statement 포맷 방식은 바이너리 로그 파일에 master server에서 실행되는 쿼리 문장을 기록하는 방식이다.
바이너리 로그 파일에 SQL 문장을 기록하는 방식을 문장 기반 복제 라고 하며, 변경된 레코드를 바이너리 로그에 기록하는 방식을 레코드 기반의 복제라고 한다.
문장 기반 복제에는 Mysql Replication시 주의해야할 점이 있다. master server에 쓰기 작업이 일어나고 Slave Server에 복제가 되기 전에 Slave Server에 읽기 요청이 일어난다면, 일관되지 않는 값을 얻게된다. 따라서, SQL 기반의 복제가 정상적으로 작동하려면 REPEATABLE-READ 이상의 트랜잭션 격리 수준을 사용해야 하며, 그로 인해 InnoDB 테이블에서는 레코드 간의 간격을 잠그는 갭락이나 넥스트 키 락이 필요해진다.
반면 레코드 기반의 복제는 master Slave MySQL 서버 간의 네티워크 트레픽을 많이 발생시킬 수 있지만 READ-COMMITTED 트랜잭션 격리 수준에서도 작동할 수 있으며 InnoDB 테이블에서 잠금의 경합은 줄어들게 된다.
REFERENCE
'Dev > Database' 카테고리의 다른 글
[DB]DB Partitioning [DB 파티셔닝] (0) | 2022.02.15 |
---|---|
[AWS]RDS Mysql Replication 설정 (SpringBoot + JPA + Mysql) (0) | 2021.11.10 |
[DB]트랜잭션(transaction) (0) | 2021.09.14 |
[DB]이상현상(Anomly), 함수 종속성 (Functional Dependency) (0) | 2021.09.13 |
[DB] 정규화(Normalization) (0) | 2021.09.11 |