MMM 개요 및 특징
MMM(Master-Master replication manager for MySQL)은 Perl 기반의 스크립트 집합으로, MySQL 마스터-마스터 복제 환경의 모니터링과 관리를 자동화합니다. 이름은 마스터-마스터이지만 실제 운영 시점에는 단일 노드만 쓰기를 수행하며, 나머지 마스터는 예비 상태로 일부 읽기 트래픽을 분담합니다. 이를 통해 장애 발생 시 빠른 전환과 노드 예열 효과를 동시에 얻을 수 있습니다.
MMM은 가상 IP 기반의 자동 장애 전환, 제 지연 모니터링, 슬레이브 로드 밸런싱 등을 제공합니다. 다만 완전한 데이터 일관성을 보장하지 못하므로, 최종 일관성이 허용되는 업무 환경에 적합합니다.
장단점 분석
강점:
- 오랜 기간 검증된 안정적인 오픈소스 솔루션
- MySQL 네이티브 기능 기반으로 원리 파악이 용이함
- 설치 및 설정이 간편하며, HA와 failover를 포함한 풍부한 도구 제공
- 클러스터 모드로 다수 MMM 그룹 중앙 관리 가능
약점:
- 단일 쓰기 지점으로 인해 수평 확장성에 한계 존재
- 읽기 분산은 별도 애플리케이션 로직 또는 추가 도구 필요
구성 환경
이번 구성에서는 5대 서버를 활용합니다.
| 호스트명 | IP 주소 | 역할 |
|---|---|---|
| primary-node | 10.0.0.11 | 활성 마스터 |
| standby-node | 10.0.0.12 | 예비 마스터 |
| replica-alpha | 10.0.0.13 | 슬레이브 |
| replica-beta | 10.0.0.14 | 슬레이브 |
| mmm-observer | 10.0.0.15 | 모니터 서버 |
필요 가상 IP: 쓰기용 1개, 읽기용 4개
계정 권한 요구사항:
- Monitor 계정: REPLICATION CLIENT, REPLICATION SLAVE
- Agent 계정: SUPER, REPLICATION CLIENT, PROCESS
- Replication 계정: REPLICATION SLAVE
- Tools 계정: SUPER, REPLICATION CLIENT, RELOAD
MySQL 설치 및 설정
각 노드의 /etc/my.cnf 설정 예시입니다.
primary-node (10.0.0.11)
[mysqld]
server-id = 11
datadir = /var/lib/mysql/data
log-bin = /var/lib/mysql/logs/binlog
binlog_format = ROW
relay_log = /var/lib/mysql/logs/relay-log
auto-increment-increment = 2
auto-increment-offset = 1
sync_binlog = 1
sync_master_info = 1
sync_relay_log = 1
sync_relay_log_info = 1
max_binlog_size = 128M
log_slave_updates = 1
read_only = 1
sql_mode = NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLESstandby-node (10.0.0.12)
[mysqld]
server-id = 12
datadir = /var/lib/mysql/data
log-bin = /var/lib/mysql/logs/binlog
binlog_format = ROW
relay_log = /var/lib/mysql/logs/relay-log
auto-increment-increment = 2
auto-increment-offset = 2
sync_binlog = 1
sync_master_info = 1
sync_relay_log = 1
sync_relay_log_info = 1
max_binlog_size = 128M
log_slave_updates = 1
read_only = 1
sql_mode = NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLESreplica-alpha (10.0.0.13)
[mysqld]
server-id = 13
datadir = /var/lib/mysql/data
log-bin = /var/lib/mysql/logs/binlog
binlog_format = ROW
relay_log = /var/lib/mysql/logs/relay-log
sync_binlog = 1
sync_master_info = 1
sync_relay_log = 1
sync_relay_log_info = 1
max_binlog_size = 128M
log_slave_updates = 1
read_only = 1
sql_mode = NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLESreplica-beta (10.0.0.14)
[mysqld]
server-id = 14
datadir = /var/lib/mysql/data
log-bin = /var/lib/mysql/logs/binlog
binlog_format = ROW
relay_log = /var/lib/mysql/logs/relay-log
sync_binlog = 1
sync_master_info = 1
sync_relay_log = 1
sync_relay_log_info = 1
max_binlog_size = 128M
log_slave_updates = 1
read_only = 1
sql_mode = NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES설정 적용 후 각 서버에서 MySQL 서비스를 재시작합니다.
systemctl restart mysqld필수 계정 생성 및 데이터 동기화
primary-node에서 계정을 생성합니다.
mysql -u root -p
CREATE USER 'mmm_observer'@'10.0.0.%' IDENTIFIED BY 'Secure#Pass1';
GRANT REPLICATION CLIENT ON *.* TO 'mmm_observer'@'10.0.0.%';
CREATE USER 'mmm_daemon'@'10.0.0.%' IDENTIFIED BY 'Secure#Pass1';
GRANT SUPER, REPLICATION CLIENT, PROCESS ON *.* TO 'mmm_daemon'@'10.0.0.%';
CREATE USER 'repl_sync'@'10.0.0.%' IDENTIFIED BY 'Secure#Pass1';
GRANT REPLICATION SLAVE ON *.* TO 'repl_sync'@'10.0.0.%';데이터 일관성을 위해 잠금 후 백업을 수행합니다.
mysql -e "FLUSH TABLES WITH READ LOCK; SHOW MASTER STATUS;" > /tmp/master_info.txt
mysqldump --all-databases --single-transaction > /tmp/full_backup.sql
mysql -e "UNLOCK TABLES;"백업 파일을 각 노드로 전송 후 복원합니다.
for node in standby-node replica-alpha replica-beta; do
scp /tmp/full_backup.sql $node:/tmp/
ssh $node "mysql < /tmp/full_backup.sql"
done복제 연결 설정
standby-node, replica-alpha, replica-beta에서 primary-node를 마스터로 지정합니다.
CHANGE MASTER TO
MASTER_HOST='10.0.0.11',
MASTER_USER='repl_sync',
MASTER_PASSWORD='Secure#Pass1',
MASTER_LOG_FILE='binlog.000001',
MASTER_LOG_POS=154;
START SLAVE;
SHOW SLAVE STATUS\Gprimary-node에서 standby-node를 마스터로 지정하여 양방향 복제를 완성합니다.
-- standby-node의 바이너리 로그 위치 확인 후
CHANGE MASTER TO
MASTER_HOST='10.0.0.12',
MASTER_USER='repl_sync',
MASTER_PASSWORD='Secure#Pass1',
MASTER_LOG_FILE='binlog.000001',
MASTER_LOG_POS=328;
START SLAVE;MMM 설치 및 구성
모든 서버에서 전용 계정을 생성합니다.
useradd -s /sbin/nologin mmmd저장소별 패키지 설치:
# 모니터 서버
yum install -y mysql-mmm-monitor
# 데이터베이스 서버 4대
yum install -y mysql-mmm-agent공통 설정 파일: /etc/mysql-mmm/mmm_common.conf
active_master_role writer
<host default>
cluster_interface eth0
pid_path /var/run/mysql-mmm/mmm_agentd.pid
bin_path /usr/libexec/mysql-mmm/
replication_user repl_sync
replication_password Secure#Pass1
agent_user mmm_daemon
agent_password Secure#Pass1
</host>
<host primary-node>
ip 10.0.0.11
mode master
peer standby-node
</host>
<host standby-node>
ip 10.0.0.12
mode master
peer primary-node
</host>
<host replica-alpha>
ip 10.0.0.13
mode slave
</host>
<host replica-beta>
ip 10.0.0.14
mode slave
</host>
<role writer>
hosts primary-node, standby-node
ips 10.0.0.250
mode exclusive
</role>
<role reader>
hosts primary-node, standby-node, replica-alpha, replica-beta
ips 10.0.0.251, 10.0.0.252, 10.0.0.253, 10.0.0.254
mode balanced
</role>설정 파일을 모든 노드에 배포합니다.
for ip in 10.0.0.{11,12,13,14}; do
scp /etc/mysql-mmm/mmm_common.conf $ip:/etc/mysql-mmm/
done각 데이터베이스 서버의 에이전트 식별자를 설정합니다.
# primary-node 예시
echo "include mmm_common.conf
this primary-node" > /etc/mysql-mmm/mmm_agent.conf모니터 서버 설정: /etc/mysql-mmm/mmm_mon.conf
include mmm_common.conf
<monitor>
ip 10.0.0.15
pid_path /var/run/mysql-mmm/mmm_mond.pid
bin_path /usr/libexec/mysql-mmm
status_path /var/lib/mysql-mmm/mmm_mond.status
ping_ips 10.0.0.11, 10.0.0.12, 10.0.0.13, 10.0.0.14
auto_set_online 60
</monitor>
<host default>
monitor_user mmm_observer
monitor_password Secure#Pass1
</host>
debug 0서비스 기동
# 모니터 서버
chkconfig mysql-mmm-monitor on
service mysql-mmm-monitor start
# 데이터베이스 서버
chkconfig mysql-mmm-agent on
service mysql-mmm-agent start장애 전환 검증
초기 클러스터 상태를 확인합니다.
mmm_control show출력 예시:
primary-node(10.0.0.11) master/ONLINE. Roles: reader(10.0.0.251), writer(10.0.0.250)
standby-node(10.0.0.12) master/ONLINE. Roles: reader(10.0.0.254)
replica-alpha(10.0.0.13) slave/ONLINE. Roles: reader(10.0.0.252)
replica-beta(10.0.0.14) slave/ONLINE. Roles: reader(10.0.0.253)primary-node의 MySQL을 중지하여 장애를 시뮬레이션합니다.
systemctl stop mysqld모니터에서 상태를 확인하면 쓰기 VIP가 standby-node로 이동하고, primary-node는 HARD_OFFLINE 상태로 전환됩니다.
mmm_control show
primary-node(10.0.0.11) master/HARD_OFFLINE. Roles:
standby-node(10.0.0.12) master/ONLINE. Roles: reader(10.0.0.254), writer(10.0.0.250)
replica-alpha(10.0.0.13) slave/ONLINE. Roles: reader(10.0.0.251), reader(10.0.0.252)
replica-beta(10.0.0.14) slave/ONLINE. Roles: reader(10.0.0.253)슬레이브들의 복제 마스터가 standby-node로 자동 재설정되었는지 확인합니다.
SHOW SLAVE STATUS\G
-- Master_Host: 10.0.0.12장애 노드를 복구하면 자동으로 ONLINE 상태로 전환되나, 쓰기 역할은 기존 마스터를 유지합니다.
핵심 동작 원리
- 가상 IP는 모니터 프로세스가 관리하며, 모니터 미구동 시에도 기존 할당된 VIP는 유지됨
- 에이전트는 모니터의 지시에 따르며, 단독으로 장애를 처리할 수 없음
- 모니터는 데이터베이스 상태, 서버 가용성, 복제 지연을 주기적으로 점검
- 장애 복구 후
auto_set_online시간(기본 60초) 경과 후 자동 ONLINE 전환 - 모니터가 활성 마스터의
read_only를 OFF로, 나머지는 ON으로 설정함
운영 시 고려사항
예비 마스터 노드 장애는 클러스터에 영향을 주지 않으며, 단지 읽기 역할만 제거됩니다. 활성 마스터 장애 시 예비 마스터가 쓰기를 인수하고, 모든 슬레이브는 새 마스터를 자동 추적합니다.
다만 복제 지연이 발생한 상태에서 장애가 나면 데이터 불일치가 발생할 수 있습니다. 이를 완화하기 위해 반동기 복제(semi-sync replication) 적용을 권장하며, MariaDB 또는 MySQL 5.7 이상의 멀티스레드 슬레이브로 복제 성능을 향상시킬 수 있습니다.