본 수업은 Mysql에 대한 지식과 리플리케이션 그리고 가상(사설) IP에 대한 지식을 필요로 합니다
Multi-Master Replication for Mysql 홈페이지
서버 구성
ip | 호스트 | 서버 ID | |
---|---|---|---|
모니터링 서버 | 192.168.0.10 | mon | - |
master 1 | 192.168.0.11 | db1 | 1 |
master 2 | 192.168.0.12 | db2 | 2 |
slave 1 | 192.168.0.13 | db3 | 3 |
slave 2 | 192.168.0.14 | db4 | 4 |
가상 IP의 구성
ip | 역활(role) | 설명 |
---|---|---|
192.168.0.100 | 쓰기 (writer) | 쓰기 쿼리 (update, insert, delete등)가 접근할 IP |
192.168.0.101 | 읽기 (reader) | 읽기 쿼리 (select)가 접근할 IP |
192.168.0.102 | 읽기 (reader) | |
192.168.0.103 | 읽기 (reader) | |
192.168.0.104 | 읽기 (reader) |
MYSQL 설정
모든 호스트의 my.cnf 파일을 아래와 같이 수정한다. (/etc/my.cnf, /etc/mysql/my.cnf에 주로 위치한다)
다음 설정 중 server_id 값은 서버마다 유일한 식별값이어야 한다. 중복되면 안된다.
server-id = 1 log_bin = /var/log/mysql/mysql-bin.log log_bin_index = /var/log/mysql/mysql-bin.log.index relay_log = /var/log/mysql/mysql-relay-bin relay_log_index = /var/log/mysql/mysql-relay-bin.index expire_logs_days = 10 max_binlog_size = 100M log_slave_updates = 1
외부에서 mysql 서버에 접근할 수 있게 접근 제한을 해제한다.
bind-address = 0.0.0.0
auto_increment_increment는 ID값을 auto increment 할 때 증가되는 숫자의 크기를 지정한다. 예를들어 이 값이 2면 2,4,6과 같은 식으로 값이 증가한다.
auto_increment_increment = 2
auto_increment_offset는 auto increment의 최초시작 값을 지정한다. 두대의 마스터가 있다면 하나는 1, 다른 하나는 2를 지정한다. 그래야 상호 리플리케이션 과정에서 고유값이 충돌하지 않는다.
auto_increment_offset = 1
서버를 재시작한다.
/etc/init.d/mysql restart
사용자 생성
각 서버에 3가지 타입의 사용자를 생성해야 한다.
구분 | 설명 | 요구권한 |
---|---|---|
모니터링 | mmm monitor가 중앙에서 각 서버의 상태를 체크하기 위해서 필요한 계정 | replication client |
에이전트 유저 | 서버를 mmm을 통해서 제어하거나, 서버에 문제가 생겼을 때 제어를 수행하는 에이전트의 계정 | super, replication client, process |
복제 유저 | 복제를 위한 계정 | replication slave |
아래의 명령을 mysql 콘솔에 실행한다.
GRANT REPLICATION CLIENT ON *.* TO 'mmm_monitor'@'192.168.0.%' IDENTIFIED BY 'monitor_password'; GRANT SUPER, REPLICATION CLIENT, PROCESS ON *.* TO 'mmm_agent'@'192.168.0.%' IDENTIFIED BY 'agent_password'; GRANT REPLICATION SLAVE ON *.* TO 'replication'@'192.168.0.%' IDENTIFIED BY 'replication_password'; flush privileges;
동기화 작업
db1에 기본 데이터가 있다고 가정하고, db1의 데이터를 dump해서 이를 각 서버에 복원한다.
아래의 명령을 db1의 mysql 콘솔에 실행한다 .다음 명령어는 mysqldump를 실행하기 전에 각 테이블을 읽기전용으로 변경한다.
(db1) mysql > FLUSH TABLES WITH READ LOCK;
다음 명령을 실행해서 db1의 상태를 확인한다. db1의 파일명(File)과 바이너리 로그 포지션(Position)을 기록해둔다. 나머지 서버들은 dump된 데이터를 기반으로 할 것이기 때문에 db1의 바이너리 로그 상의 포지션을 정확하게 지정해야 동기화에서 오류가 발생하지 않는다.
(db1) mysql> show master status\G
*************************** 1. row *************************** File: mysql-bin.000001 Position: 1864 Binlog_Do_DB: Binlog_Ignore_DB: 1 row in set (0.00 sec)
mysql 클라이언트를 닫으면 lock가 해제되므로 닫으면 안된다. 쉘을 새로 실행해서 그곳에서 다음 작업을 실행한다.
db1$ mysqldump -u root -p --all-databases > /tmp/database-backup.sql
FLUSH ... LOCK 를 실행한 쉘에서 다음 명령을 실행한다.
(db1) mysql> UNLOCK TABLES;
덤프한 파일을 각 서버로 전송한다.
db1$ scp /tmp/database-backup.sql <user>@192.168.0.12:/tmp db1$ scp /tmp/database-backup.sql <user>@192.168.0.13:/tmp db1$ scp /tmp/database-backup.sql <user>@192.168.0.14:/tmp
각 서버에서 백업한 데이터를 복원한다.
db2$ mysql -u root -p < /tmp/database-backup.sql db3$ mysql -u root -p < /tmp/database-backup.sql db4$ mysql -u root -p < /tmp/database-backup.sql
db1의 권한을 다른 테이블에도 적용하기 위해서 아래 명령을 실행한다.
(db2) mysql> FLUSH PRIVILEGES; (db3) mysql> FLUSH PRIVILEGES; (db4) mysql> FLUSH PRIVILEGES;
debian이나 ubuntu의 경우, msyql를 시작하고 중지하기 위해서 db1의 /etc/mysql/debian.cnf 파일을 db2,3,4에 복사한다.
원래 이 작업은 mysql을 start, stop 할 때 mysql 사용자 계정 중 debian-sys-maint 을 호출해서 DB를 제어하기 위한 것이라고 하는데, 막상 이 값이 같으나 다르나 실제로는 잘 작동하는 것으로 보인다. 원인을 아시는 분은 알려주시면 후사 하겠습니다. ㅎㅎ
이렇게 해서 db1과 db2,3,4의 데이터를 동기화 했다.
복제 설정
db2,3,4의 복제를 설정한다. 아래 명령을 이용해서 db1를 제외한 서버들에게 마스터가 누구인가를 알려준다. 또 db1에서 추출한 dump 이후에 갱신된 데이터에 대한 좌표(파일과 포지션)를 알려줌으로서 dump 데이터 이후부터 슬레이브 구동까지 누락될 데이터가 생기는 것을 방지한다.
각 슬레이브에 아래와 같이 명령해 슬레이브(패시브 마스터 포함)가 마스터 액티브를 바라보게 한다. 여기서 <file>, <position>은 db1에서 내린 show master status의 결과 값을 사용해야 한다.
(db2) mysql> CHANGE MASTER TO master_host='192.168.0.11', master_port=3306, master_user='replication', master_password='replication_password', master_log_file='<file>', master_log_pos=<position>; (db3) mysql> CHANGE MASTER TO master_host='192.168.0.11', master_port=3306, master_user='replication', master_password='replication_password', master_log_file='<file>', master_log_pos=<position>; (db4) mysql> CHANGE MASTER TO master_host='192.168.0.11', master_port=3306, master_user='replication', master_password='replication_password', master_log_file='<file>', master_log_pos=<position>;
슬레이브를 구동한다.
(db2) mysql> START SLAVE; (db3) mysql> START SLAVE; (db4) mysql> START SLAVE;
각각의 슬레이브에서 show slave status를 실행하고, 슬레이브가 잘 작동하는지 확인한다. Slave_IO_Running, Slave_SQL_Running의 값이 모두 Yes인지 확인한다. 아니라면 문제가 있는 것이다.
db2) mysql> SHOW SLAVE STATUS\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.0.11 Master_User: replication Master_Port: 3306 Connect_Retry: 60 … (db3) mysql> SHOW SLAVE STATUS\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.0.11 Master_User: replication Master_Port: 3306 Connect_Retry: 60 … (db4) mysql> SHOW SLAVE STATUS\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.0.11 Master_User: replication Master_Port: 3306 Connect_Retry: 60 …
db1을 db2의 슬레이브로 설정해서 마스터-마스터 복제구성을 완료해야 한다.
(db2) mysql> SHOW MASTER STATUS; +------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+------------------+ | mysql-bin.000001 | 98 | | | +------------------+----------+--------------+------------------+ 1 row in set (0.00 sec)
db1의 마스터로 db2를 바라보게하고, db2와 동기화 시점을 설정한다.
db1) mysql> CHANGE MASTER TO master_host = '192.168.0.12', master_port=3306, master_user='replication', master_password='replication_password', master_log_file='<file>', master_log_pos=<position>;
슬레이브 시작
(db1) mysql> START SLAVE;
db1의 슬레이브가 동작하고 있는지를 확인한다.
(db1) mysql> SHOW SLAVE STATUS\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.0.12 Master_User: <replication> Master_Port: 3306 Connect_Retry: 60
MMM 설치
유저 생성(옵션)
useradd --comment "MMM Script owner" --shell /sbin/nologin mmmd
다운로드
http://mysql-mmm.org/downloads
모니터링 호스트
의존성이 있는 모듈을 먼저 설치한다.
mon$ aptitude install liblog-log4perl-perl libmailtools-perl liblog-dispatch-perl libclass-singleton-perl libproc-daemon-perl libalgorithm-diff-perl libdbi-perl libdbd-mysql-perl
다운로드한 파일을 설치한다.
mon$ dpkg -i mysql-mmm-common_*.deb mysql-mmm-monitor*.deb
데이터베이스 호스트
ubuntu 설치
db1,2,3,4$ aptitude install liblog-log4perl-perl libmailtools-perl liblog-dispatch-perl iproute libnet-arp-perl libproc-daemon-perl libalgorithm-diff-perl libdbi-perl libdbd-mysql-perl
db1,2,3,4$ dpkg -i mysql-mmm-common_*.deb mysql-mmm-agent_*.deb
Redhat 설치
db1,2,3,4$ yum install -y mysql-mmm-agent
db1,2,3,4$ mysql-mmm-agent.noarch 0:2.2.1-1.el5
설치된 의존성 모듈 목록
libart_lgpl.x86_64 0:2.3.17-4 mysql-mmm.noarch 0:2.2.1-1.el5 perl-Algorithm-Diff.noarch 0:1.1902-2.el5 perl-DBD-mysql.x86_64 0:4.008-1.rf perl-DateManip.noarch 0:5.44-1.2.1 perl-IPC-Shareable.noarch 0:0.60-3.el5 perl-Log-Dispatch.noarch 0:2.20-1.el5 perl-Log-Dispatch-FileRotate.noarch 0:1.16-1.el5 perl-Log-Log4perl.noarch 0:1.13-2.el5 perl-MIME-Lite.noarch 0:3.01-5.el5 perl-Mail-Sender.noarch 0:0.8.13-2.el5.1 perl-Mail-Sendmail.noarch 0:0.79-9.el5.1 perl-MailTools.noarch 0:1.77-1.el5 perl-Net-ARP.x86_64 0:1.0.6-2.1.el5 perl-Params-Validate.x86_64 0:0.88-3.el5 perl-Proc-Daemon.noarch 0:0.03-1.el5 perl-TimeDate.noarch 1:1.16-5.el5 perl-XML-DOM.noarch 0:1.44-2.el5 perl-XML-Parser.x86_64 0:2.34-6.1.2.2.1 perl-XML-RegExp.noarch 0:0.03-2.el5 rrdtool.x86_64 0:1.2.27-3.el5 rrdtool-perl.x86_64 0:1.2.27-3.el5
MMM 설정
아래의 설정 파일을 모든 호스트(모니터링 호스트 포함)의 /etc/mysql-mmm/mmm_common.conf 파일에 적용한다.
active_master_role writer <host default> cluster_interface eth0 pid_path /var/run/mmmd_agent.pid bin_path /usr/lib/mysql-mmm/ replication_user replication replication_password replication_password agent_user mmm_agent agent_password agent_password </host> <host db1> ip 192.168.0.11 mode master peer db2 </host> <host db2> ip 192.168.0.12 mode master peer db1 </host> <host db3> ip 192.168.0.13 mode slave </host> <host db4> ip 192.168.0.14 mode slave </host> <role writer> hosts db1, db2 ips 192.168.0.100 mode exclusive </role> <role reader> hosts db1, db2, db3, db4 ips 192.168.0.101, 192.168.0.102, 192.168.0.103, 192.168.0.104 mode balanced </role>
모니터링 호스트를 제외한 데이터베이스 호스트의 /etc/mysql-mmm/mmm_agent.conf 파일을 수정한다. 'db1'은 각 서버의 서버명에 맞게 변경해야 한다.
include mmm_common.conf
this db1
모니터링 호스트에 /etc/mysql-mmm/mmm_mon.conf 파일을 아래와 같이 수정한다. ping_ips 중 192.168.0.1은 네트워크 스위치를 의미한다.
include mmm_common.conf <monitor> ip 127.0.0.1 pid_path /var/run/mmmd_mon.pid bin_path /usr/lib/mysql-mmm/ status_path /var/lib/misc/mmmd_mon.status ping_ips 192.168.0.1, 192.168.0.11, 192.168.0.12, 192.168.0.13, 192.168.0.14 </monitor> <host default> monitor_user mmm_monitor monitor_password monitor_password </host> debug 0
MMM 구동하기
Debian/ubuntu
데이터베이스 호스트의 /etc/default/mysql-mmm-agent 파일을 아래와 같이 수정한다.
ENABLED = 1
Red Hat
자동실행을 위해서 아래와 같이 해준다.
chkconfig mysql-mmm-agent on
시동한다.
/etc/init.d/mysql-mmm-agent start
모니터링 시작
모니터링 호스트의 /etc/default/mysql-mmm-monitor 파일을 아래와 같이 수정한다.
ENABLED=1
그리고 시작한다.
/etc/init.d/mysql-mmm-monitor start
참시 기다렸다가 아래와 같이 실행하면 유사하게 출력되야 정상이다.
mon$ mmm_control show db1(192.168.0.11) master/AWAITING_RECOVERY. Roles: db2(192.168.0.12) master/AWAITING_RECOVERY. Roles: db3(192.168.0.13) slave/AWAITING_RECOVERY. Roles: db4(192.168.0.14) slave/AWAITING_RECOVERY. Roles:
그런데 각 호스트의 상태가 AWATING_RECOVERY 이다. 명시적으로 호스트를 모니터에 등록해줘야 한다. 아래는 문제가 발생했을 때 자세한 정보를 얻기 위한 로깅 장면이다.
mon$ tail /var/log/mysql-mmm/mmm_mon.warn … 2009/10/28 23:15:28 WARN Detected new host 'db1': Setting its initial state to 'AWAITING_RECOVERY'. Use 'mmm_control set_online db1' to switch it online. 2009/10/28 23:15:28 WARN Detected new host 'db2': Setting its initial state to 'AWAITING_RECOVERY'. Use 'mmm_control set_online db2' to switch it online. 2009/10/28 23:15:28 WARN Detected new host 'db3': Setting its initial state to 'AWAITING_RECOVERY'. Use 'mmm_control set_online db3' to switch it online. 2009/10/28 23:15:28 WARN Detected new host 'db4': Setting its initial state to 'AWAITING_RECOVERY'. Use 'mmm_control set_online db4' to switch it online.
아래와 같이 하면 모니터링에 명시적으로 각호스트가 등록되고 이제부터 각각의 호스트를 제어할 수 있다.
mon$ mmm_control set_online db1 OK: State of 'db1' changed to ONLINE. Now you can wait some time and check its new roles! mon$ mmm_control set_online db2 OK: State of 'db2' changed to ONLINE. Now you can wait some time and check its new roles! mon$ mmm_control set_online db3 OK: State of 'db3' changed to ONLINE. Now you can wait some time and check its new roles! mon$ mmm_control set_online db4 OK: State of 'db4' changed to ONLINE. Now you can wait some time and check its new roles!