본문 바로가기

기술이야기

Mysql(Mariadb) Replicaiton 구축하기

 

0. 준비


실무에선 보통 단일 Mysql 장비로 서비스를 운영하지 않는다. 트래픽이 증가하다 보면 자연스럽게 병목현상이 발생하기 때문이다. 아무리 애플리케이션 단에서 대용량 처리가 가능하다 해도 DB에서 병목현상이 발생하면 의미가 없기 마련이다. 따라서 DB까지 부하 분산 작업이 필요하다.

 

DB 단에서 부하 분산을 위한 방법은 여러가지 있다. 그중에서 가장 일반적이고 쉽게 적용할 수 있는 방법을 소개해보려고 한다. 바로 Replication(복제) 방식이다. Replication 방식은 쓰기(Insert, Update, Delete) 연산을 할 수 있는 Master 장비 1대와 읽기(Select) 연산만 할 수 있는 Slave 장비로 구성되어 있다.

 

 * 보통 읽기 연산이 쓰기 연산보다 많이 실행되므로 하나 이상의 Slave 장비를 두곤 한다.

 

 

Mysql Replication 구조, 구글이미지 참조

 

Replication 동작 흐름은 간략하게 이렇다. 애플리케이션 단에서 쓰기 쿼리문을 Master 장비로 실행한다. 이때 Master 장비는 실행 로그를 바이너리 로그(bin-log)하게 되고, 이 로그를 Slave 장비로 가져와 똑같은 쿼리문을 실행하게 된다. 추가적으로 log_slave_updates가 활성화가 되면 Slave 장비 또한 바이너리 로그를 생성할 수 있기 때문에 또 다른 서버의 Master 역할을 할 수 있다. 

 

* 위 (복제) 과정은 비동기 방식으로 수행한다. 따라서 Master에 변경된 데이터가 아직 Slave에 반영되지 못한 채 Slave 데이터를 읽어 들일 경우 데이터 정합성 문제가 생길 수 있다.

 

 

아래 글은Master 장비 1대와 Slave 장비 1대를 연동하는 방법이며, Mysql 대신 Mariadb(Mysql 대신 사용 가능하다)가 설치되어 있다.

 

 

 

1. Master 설정


Replication 작업은 간단하다. 가장 먼저 설치된 Master 장비의 MariaDB 서버에 접속하고 유저를 생성한다. root 계정을 사용하는 것은 보안상 좋지 않기 때문에 Replication에 사용할 유저를 새로 생성한다.

 

mysql -u root -p
MariaDB [(none)]> CREATE USER 'user'@localhost IDENTIFIED BY '1234';
MariaDB [(none)]> CREATE USER 'user'@'%' IDENTIFIED BY '1234'; #  '%' 속성으로 모든 IP에서 접근 가능
MariaDB [(none)]> GRANT REPLICATION SLAVE ON *.* TO 'user'@'%' IDENTIFIED BY '1234'; 
MariaDB [(none)]> flush privileges;


#생성한 user, host, password 정보 확인
MariaDB [(none)]> use mysql;
MariaDB [mysql]> select host, user, password from user;

 

 

이후 MariaDB의 서버 설정을 아래처럼 변경한다.

 

# ubuntu 서버일 경우 /etc/mysql/my.cnf 파일을 수정
sudo vim /etc/my.cnf 

## my.cnf
[mysqld]
server-id = 1 # master, slave서버의 id 값이 달라야 함
log-bin = mysql-bin # 바이너리 로그 파일 위치

# mariadb 재시작
sudo systemctl restart mariadb
 

 

 

재시작까지 마쳤다면 mariadb에 접속하여 아래 명령어를 실행하면 바이너리 로그 파일 위치와 Position 정보를 알 수 있다. 두 정보는 이후 Slave 서버에서 Master와 연결할 때 필요하므로 기억하고 있자.

 

* 쿼리가 실행할 때마다 값이 바뀐다. 만약 Master-Slave 동기화가 끊겼을 경우 Slave 장비 쪽에서 Master의 바이너리 로그 정보를 확인하여 수정이 필요하다.

 

Master의 바이너리 로그 정보

 

 

 

2. Slave 설정


 

먼저 Slave 서버 설정을 아래처럼 추가한다. 

# Ubuntu 서버일 경우 /etc/mysql/my.cnf 파일을 수정
sudo vim /etc/my.cnf


## my.cnf 파일
[mysqld]
server-id = 2 # master, slave1, slave2 모두 id 값이 달라야 함. 
read_only # 권장


sudo systemctl restart mariadb
 

읽기 연산만 가능한 장비로 만들기 위해선 read_only 속성을 추가해야 한다. 추가할 경우 쓰기 쿼리가 실행되면 아래처럼 에러가 발생한다.

 

read_only 설정 결과

 

 

설정 추가 후 mariadb 재시작이 완료되면 mariadb에 접속한다.

mysql -u root -p

 

 

위 Master의 바이너리 파일 위치 및 position 정보를 참고하여 아래 명령어 수행한다. 그 후 Slave 상태 출력 명령어를 사용하여 Master 정보가 제대로 설정되었는지 확인한다.

MariaDB [(none)]> CHANGE MASTER TO MASTER_HOST='마스터IP', MASTER_PORT=3306, MASTER_USER='user', MASTER_PASSWORD='qwer1234', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=154;
MariaDB [(none)]> start slave;

MariaDB [(none)]> show slave status; # Master서버의 IP, 바이너리 로그 파일명, position 정보 확인 가능​

 

여기까지만 하면 Replication 작업은 완료된다. 이제 정상적으로 Master-Slave 연동이 되었는지 테스트만 하면 된다.

 

 

 

3. 테스트


 

1. 테이블 생성

1-1. Master 서버에 테스트할 데이터베이스와 테이블 생성한다.

MariaDB [(none)]> CREATE DATABASE `test`;
MariaDB [(none)]> use test;
Database changed
MariaDB [test]>  CREATE TABLE `user` (
	`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
	`name` VARCHAR(255) NULL DEFAULT NULL,
	PRIMARY KEY (`id`)
);

 

1-2. Slave 서버에도 정상적으로 생성되었는지 확인한다.

MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| test               |
+--------------------+
2 rows in set (0.00 sec)

MariaDB [(none)]> use test;
Database changed
MariaDB [test]> show tables;
+----------------+
| Tables_in_test |
+----------------+
| user           |
+----------------+
1 row in set (0.00 sec)

 

 

2. 데이터 삽입

2-1.  Master 서버의 user 테이블에 데이터 삽입한다.

MariaDB [test]> INSERT INTO `user` (`name`) VALUES ('name1');
Query OK, 1 row affected (0.00 sec)

2-2. Slave 서버에도 정상적으로 데이터가 삽입되었는지 확인한다.

MariaDB [test]> SELECT * FROM `user`;
+----+-------+
| id | name  |
+----+-------+
|  1 | name1 |
+----+-------+
1 row in set (0.00 sec)

 

 

 

4. 참고


 

1. Master-Slave 동기화가 끊길 경우

 

먼저 Slave 장비에 접속하여 아래 명령을 수행한다. 

stop slave; # 서버 자체 중지가 아닌 Slave 역할로써의 중지

 

 

이후 Master 장비에 접속하여 현재 바이너리 파일 위치와 포지션 정보를 확인한다. 

flush logs; # 활성화된 바이너리를 닫고 새로운 바이너리 파일을 연다.
show master status; # 새로운 파일 위치와 포지션 값 확인한다.

 

 

마지막으로 Slave 서버에서 위 Master 정보로 아래 명령어를 실행한다. 그리고 정상적으로 연동이 되었는지 확인한다.

CHANGE MASTER TO MASTER_LOG_FILE='파일위치', MASTER_LOG_POS='포지션';
start slave;