# Database Replication

MHA(Master High Availability)란, Master DB가 장애로 서비스가 불가능한 상태가 되면, 자동으로 failover를 수행하여 slave DB를 master DB로 승격시켜 **서비스 다운타임을 최소화 auto failover 솔루션이다.**

[![image.png](http://138.2.116.150/uploads/images/gallery/2023-07/scaled-1680-/image.png)](http://138.2.116.150/uploads/images/gallery/2023-07/image.png)

MHA구조는 MHA manager도 추가로 구성 해야 하지만, 기본적인 이중화 구성은 MasterDB와 SlaveDB구성으로 2개의 DB를 묶어서 사용 가능 하다.

이번 데모에서는 2개의 DB를 묶어서 Master와 Slave(replication)DB 구조를 설계 해 보겠다.

💡데모에 사용된 시스템

- 2개의 AWS EC2 인스턴스 (Cloud용 Virtual Machine)
- 1개는 x86\_64 CPU 아키텍처를 사용 그리고 1개는 ARM CPU 아키텍처를 사용함
- DB-Master 인스턴스 (172.31.33.8) ➖ RHEL 9.2
- DB-Slave 인스턴스 (172.31.23.223) ➖ RHEL 9.2

#### **EC2 인스턴스 생성**

첫 번째로 AWS 계정에 로그인 후 EC2 인스턴스를 선택 한다

[![image.png](http://138.2.116.150/uploads/images/gallery/2023-07/scaled-1680-/kaeimage.png)](http://138.2.116.150/uploads/images/gallery/2023-07/kaeimage.png)

그 후 왼쪽 메뉴에서 'instances'를 선택 한다

[![image.png](http://138.2.116.150/uploads/images/gallery/2023-07/scaled-1680-/ljHimage.png)](http://138.2.116.150/uploads/images/gallery/2023-07/ljHimage.png)

오른쪽 상단에서 'Launch Instances'를 선택

[![image.png](http://138.2.116.150/uploads/images/gallery/2023-07/scaled-1680-/Uauimage.png)](http://138.2.116.150/uploads/images/gallery/2023-07/Uauimage.png)

인스턴스 이름, 이미지 및 CPU 아키텍처 지정

[![image.png](http://138.2.116.150/uploads/images/gallery/2023-07/scaled-1680-/WjGimage.png)](http://138.2.116.150/uploads/images/gallery/2023-07/WjGimage.png)

Slave용 DB를 위해서 ARM 아키텍처를 사용 했다

[![image.png](http://138.2.116.150/uploads/images/gallery/2023-07/scaled-1680-/Rknimage.png)](http://138.2.116.150/uploads/images/gallery/2023-07/Rknimage.png)

나머지 설정은 보안 그룹, 인스턴스 타입 그리고 스토리지 설정이다

[![image.png](http://138.2.116.150/uploads/images/gallery/2023-07/scaled-1680-/58timage.png)](http://138.2.116.150/uploads/images/gallery/2023-07/58timage.png)

<p class="callout info">보안 그룹은 AWS용 Firewall이라고 생각 하면 된다.  
스토리지는 기본적으로 Block 스토리지를 제공 한다</p>

그 외 인스턴스를 생성 하기 전, SSH를 위해 키 페어를 생성 한다

[![image.png](http://138.2.116.150/uploads/images/gallery/2023-07/scaled-1680-/Fjgimage.png)](http://138.2.116.150/uploads/images/gallery/2023-07/Fjgimage.png)

위 설정과 같이 2개의 인스턴스를 생성 하면

[![image.png](http://138.2.116.150/uploads/images/gallery/2023-07/scaled-1680-/C7zimage.png)](http://138.2.116.150/uploads/images/gallery/2023-07/C7zimage.png)

이제 키 페어를 통해서 두개의 인스턴스에 SSH접속을 한다

[![image.png](http://138.2.116.150/uploads/images/gallery/2023-07/scaled-1680-/GnZimage.png)](http://138.2.116.150/uploads/images/gallery/2023-07/GnZimage.png)

OS확인 및 CPU 아키텍처 확인 실행

```bash
## 마스터 DB OS 확인
[root@ip-172-31-33-8 ~]# cat /etc/os-release 
NAME="Red Hat Enterprise Linux"
VERSION="9.2 (Plow)"

## 마스터 DB CPU 아키텍처 확인
[root@ip-172-31-33-8 ~]# lscpu
Architecture:            x86_64
  CPU op-mode(s):        32-bit, 64-bit
  Address sizes:         46 bits physical, 48 bits virtual
  Byte Order:            Little Endian
CPU(s):                  1
  On-line CPU(s) list:   0
Vendor ID:               GenuineIntel
  BIOS Vendor ID:        Intel
  Model name:            Intel(R) Xeon(R) CPU E5-2686 v4 @ 2.30GHz

## Slave DB OS 확인
[root@ip-172-31-23-223 ~]# cat /etc/os-release 
NAME="Red Hat Enterprise Linux"
VERSION="9.2 (Plow)"

## Slave DB CPU 아키텍처 확인
[root@ip-172-31-23-223 ~]# lscpu
Architecture:           aarch64
  CPU op-mode(s):       32-bit, 64-bit
  Byte Order:           Little Endian
CPU(s):                 2
  On-line CPU(s) list:  0,1
Vendor ID:              ARM
  BIOS Vendor ID:       AWS
  Model name:           Neoverse-N1
    BIOS Model name:    AWS Graviton2
```

#### **DB 설치 및 설정**

이번 데모에서는 MariaDB v15.1를 사용했다

<p class="callout info">mariaDB의 개발자인 Monty는 mysql 회사를 나와 MontyProgram AB라는 회사를 차리면서 mariaDB를 만들게 되었다.  
자세한 mariaDB와 mysql 차이에 대한 블로그는 [여기](https://sabarada.tistory.com/164)에서 확인.</p>

MariaDB 설정은 일부 Master와 Slave에서는 동일하다. 아래와 같이 Master 및 Slave 서버에서 mariaDB 초기 설정을 진행 한다

```bash
# 패키지 업데이트
sudo dnf update -y

# MariaDB 패키지 설치
sudo dnf -y install mariadb-*

# MariaDB 데몬 시작
sudo systemctl enable mariadb
sudo systemctl start mariadb

# MasteDB에서의 MariaDB 버전 확인
[root@ip-172-31-33-8 ~]# mariadb --version
mariadb  Ver 15.1 Distrib 10.5.16-MariaDB, for Linux (x86_64) using  EditLine wrapper

# SlaveDB에서의 MariaDB 버전 확인
[root@ip-172-31-23-223 ~]# mariadb --version
mariadb  Ver 15.1 Distrib 10.5.16-MariaDB, for Linux (aarch64) using  EditLine wrapper

# root 계정으로 MariaDB 최초 설정 스크립트 실행 
sudo su - root
mysql_secure_installation

# 초기 암호는 비워있다
Enter current password for root (enter for none): 
OK, successfully used password, moving on...

Remove anonymous users? [Y/n] y
 ... Success!

Disallow root login remotely? [Y/n] n
 ... skipping.

Remove test database and access to it? [Y/n] y
 - Dropping test database...
 ... Success!
 
Removing privileges on test database...
 ... Success!
 
Reload privilege tables now? [Y/n] y
 ... Success!

Cleaning up...

All done!
Thanks for using MariaDB!
```

이제부터 마스터DB에서 실행 한다

```bash
# MariaDB 설정 파일안에 추가
vi /etc/my.cnf.d/mariadb-server.cnf 

log-bin=mysql-bin
server-id=1

# MariaDBMS 접속
mysql -u root

# 사용할 테스트 DB 생성
MariaDB [(none)]> create database testDB;

# 테스트 DB 생성 여부 확인
MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| testDB             |
+--------------------+
4 rows in set (0.000 sec)

# Master DB 계정 생성 및 Privileges 설정
MariaDB [mysql]> grant all privileges on testDB.* to 'Master'@'%' identified by '1';
Query OK, 0 rows affected (0.003 sec)

# SlaveDB replication 설정
MariaDB [mysql]> grant replication slave on *.* to 'Slave'@'%'identified by '1';
Query OK, 0 rows affected (0.001 sec)

## 그 후 DBMS 환경 종료 후 mariadb 서비스 재시작
MariaDB [mysql]> exit
systemctl restart mariadb

# SlaveDB 설정을 위해 Position ID 확인
mysql -u root -p -e "show master status"
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000003 |      342 |              |                  |
+------------------+----------+--------------+------------------+

# DB Backup 설정
mysqldump -u root --all-databases > backup.sql

# SCP를 통해 DB Backup을 SlaveDB에 이동
scp backup.sql root@172.31.23.223:/root/
```

그리고 SlaveDB 설정

```bash
# MariaDB 설정 파일에 추가 
vi /etc/my.cnf.d/mariadb-server.cnf 

server-id=2
replicate-do-db='testDB'

# MasterDB Backup 데이터 받기
sudo su - root
mysql -u root< backup.sql 

# MariaDBMS 접속
mysql -u root

# MasterDB과 동일한 DB 확인
MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| testDB             |         
| information_schema |
| mysql              |
| performance_schema |
+--------------------+
4 rows in set (0.007 sec)

# Slave 설정
MariaDB [(none)]> change master to master_host='172.31.33.8',
    -> master_user='Slave',
    -> master_password='1',
    -> master_log_file='mysql-bin.000003',
    -> master_log_pos=342;
Query OK, 0 rows affected (0.009 sec)

# MariaDB 재시작
systemctl restart mariadb
```

이제 Master와 Slave 데이터베이스 구조는 완성 되었다. 그러면 테스트 용도로 생성한 'testDB'는 서로 묶여있는지 확인을 위해 아래와 같이 테스트 용 데이터를 생성 해 보았다

```bash
## MasterDB에서의 작업
[root@ip-172-31-33-8 ~]# mysql -u root
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 4
Server version: 10.5.16-MariaDB-log MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> use testDB;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
MariaDB [testDB]> show tables;
+------------------+
| Tables_in_testDB |
+------------------+
| test             |
+------------------+
1 row in set (0.000 sec)

## test2 테이블 생성
MariaDB [testDB]> create table test2 (a int);
Query OK, 0 rows affected (0.009 sec)

MariaDB [testDB]> show tables;
+------------------+
| Tables_in_testDB |
+------------------+
| test             |
| test2            |
+------------------+
2 rows in set (0.001 sec)

## test3 테스트 테이블 생성
MariaDB [testDB]> create table test3 (a int);
Query OK, 0 rows affected (0.007 sec)

MariaDB [testDB]> show tables;
+------------------+
| Tables_in_testDB |
+------------------+
| test             |
| test2            |
| test3            |
+------------------+
3 rows in set (0.000 sec)
```

SlaveDB에서 Replication유무 확인

```bash
## SlaveDB에서의 작업
[root@ip-172-31-23-223 ~]# mysql -u root
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 6
Server version: 10.5.16-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

## testDB 사용
MariaDB [(none)]> use testDB;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
# MasterDB에서 test2 테이블 생성 후 확인
MariaDB [testDB]> show tables;
+------------------+
| Tables_in_testDB |
+------------------+
| test             |
| test2            |
+------------------+
2 rows in set (0.000 sec)

# MasterDB에서 test3 테이블 생성 후 확인
MariaDB [testDB]> show tables;
+------------------+
| Tables_in_testDB |
+------------------+
| test             |
| test2            |
| test3            |
+------------------+
3 rows in set (0.000 sec)
```

#### **MHA Manager 서버를 추가 하여 MHA MySQL DB Replication 구조**

이번 데모에서는 MySQL v5.7을 사용 하여, MHA manager, MasterDB 및 SlaveDB 구조로 설정을 진행 하였다. MHA manager가 있으면 auto-failover을 할 수 있기 때문에 구성을 해 보았다.

💡데모에 사용된 시스템

- 3개의 AWS EC2 인스턴스 (Cloud용 Virtual Machine)
- 2개(MHA+Master)는 x86\_64 CPU 아키텍처를 사용 그리고 1(Slave)개는 ARM CPU 아키텍처를 사용함
- MHA-Manager 인스턴스 (172.31.45.57) ➖ RHEL 9.2
- DB-Master 인스턴스 (172.31.35.181) ➖ RHEL 9.2
- DB-Slave 인스턴스 (172.31.25.160) ➖ RHEL 9.2

EC2 인스턴스 생성 및 접속 방법은 이미 설명 하였으니 바로 OS 및 CPU Architecture로 넘어 간다.

```bash
## MHA OS 및 아키텍처 확인
$ cat /etc/os-release
NAME="Red Hat Enterprise Linux"
VERSION="9.2 (Plow)"

$ lscpu
Architecture:            x86_64

## 마스터 DB OS 및 아키텍처 확인
$ cat /etc/os-release 
NAME="Red Hat Enterprise Linux"
VERSION="9.2 (Plow)"

$ lscpu
Architecture:            x86_64

## Slave DB OS 및 아키텍처 확인
$ cat /etc/os-release 
NAME="Red Hat Enterprise Linux"
VERSION="9.2 (Plow)"

$ lscpu
Architecture:           aarch64
```

#### **DB 설치 및 설정**

이번 데모에서는 MySQL v5.7를 사용 했다

MySQL를 설치 하기 위해 rpm 패키지를 받아야 하고, 로컬 설치를 진행 해야 한다

```bash
# GPG키 import 하기
sudo rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022              

# rpm 패키지 다운로드 받기
wget https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm   

# mysql 설치
yum localinstall mysql57-community-release-el7-11.noarch.rpm
yum repolist enabled | grep "mysql.-community."
yum install mysql-community-server -y

# mysqld 서비스 시작 및 상태 확인
systemctl start mysqld
systemctl status mysqld
```