DB 복제가 걸려 있다고만 들었고 어느 장비가 어느 장비를 따라가는지는 아무도 몰랐다.
Table of contents
Open Table of contents
상황 — 상태만으로는 모자랐다
한 장비에서 복제 상태부터 봤다.
SHOW SLAVE STATUS\G
Master_Host: 10.0.0.20
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Seconds_Behind_Master: 0
Slave_IO_Running 은 정상이지만 Master_Host 하나로는 전체 구조를 모른다.
장비가 다섯인데 어느 것이 원본이고 어느 것이 사본인지 이것만으로는 알 수 없었다. 사본이 또 사본을 갖는지도 그 장비에 붙어서 다시 봐야 나온다.
검증 — 전부 돌면서 봤다
다섯 장비를 한 번에 돌면서 봤다.
$ for h in 10.0.0.20 10.0.0.21 10.0.0.22 10.0.0.23 10.0.0.24; do
echo "=== $h"
mysql -h "$h" -e "SHOW SLAVE STATUS\G" | grep -E "Master_Host|Seconds_Behind"
mysql -h "$h" -e "SHOW MASTER STATUS\G" | grep -E "File|Position"
done
Master_Host 로 본 관계가 이렇게 나왔다.
=== 10.0.0.20 (Slave 없음, Master 있음) → 원본
=== 10.0.0.21 Master_Host: 10.0.0.20 → 20 의 사본
=== 10.0.0.22 Master_Host: 10.0.0.20 → 20 의 사본
=== 10.0.0.23 Master_Host: 10.0.0.21 → 21 의 사본 (2단계)
=== 10.0.0.24 Master_Host: 10.0.0.20 → 20 의 사본
10.0.0.23 이 2단계라 10.0.0.21 이 죽으면 함께 멈춘다.
한 단계 구조라고 알고 있었으면 장애가 미치는 곳을 잘못 판단했을 것이다.
결과 — 장비 정보를 붙인 표
관계도만 적어 두는 것으로는 부족했다.
역할 주소 장비 사양 위치 용도
원본 10.0.0.20 물리 서버 16코어 64G SSD 랙 A 쓰기
사본1 10.0.0.21 물리 서버 16코어 64G SSD 랙 B 읽기(주)
사본2 10.0.0.22 가상 머신 4코어 16G 랙 A 통계 조회
사본3 10.0.0.23 가상 머신 4코어 16G 랙 B 백업 추출
사본4 10.0.0.24 물리 서버 8코어 32G 다른 IDC 재해 대비
가상 머신 인 사본은 복제가 더 잘 밀린다.
위치가 다르면 한쪽 랙이 죽었을 때 남는 것이 갈리는데 구조만 있으면 다섯 장비가 다 같아 보인다.
판단 기준 — 무엇이 무엇을 읽는지
무엇이 어느 장비를 읽는지도 함께 적었다.
애플리케이션 쓰기 → 원본(20)
애플리케이션 읽기 → 사본1(21)
통계 배치 → 사본2(22)
백업 → 사본3(23)
재해 대비 → 사본4(24), 평소 아무도 안 읽음
사본1 이 죽으면 서비스 읽기가 멈추고 사본2 가 죽으면 통계만 안 나온다.
어느 장비가 죽었을 때 무엇이 안 되는지가 이 표 하나로 갈렸다. 이것이 없으면 장애 때 무엇부터 봐야 할지를 그 자리에서 다시 조사하게 된다.
주의 — 지연과 용도별 기준
복제 지연은 계속 재서 봤다.
$ for h in $REPLICAS; do
echo -n "$h "
mysql -h "$h" -sN -e "SHOW SLAVE STATUS\G" | grep Seconds_Behind | awk '{print $2}'
done
10.0.0.21 0
10.0.0.22 412 ←
10.0.0.23 0
10.0.0.24 8
10.0.0.22 가 7분 밀려 있었는데 통계 배치가 무거운 조회를 돌려서였다.
밀리는 것 자체는 그 용도에서 괜찮았고 얼마나 밀리는지 알고 있는 것이 중요했다. 다만 MySQL 5.7 참고 매뉴얼은 Seconds_Behind_Master 를 사본의 SQL 스레드와 I/O 스레드 사이의 시간 차로 정의하고, 처리 중인 이벤트가 없으면 0 이라고 적는다. 그래서 0 이 최신이라는 뜻은 아니고 I/O 스레드가 원본에서 아직 못 받은 만큼은 여기 안 잡힌다.
사본1 10초 넘으면 알림 (서비스 읽기)
사본2 30분 넘으면 알림 (통계)
사본4 5분 넘으면 알림 (재해 대비)
하나의 기준으로 보면 한쪽은 과하고 한쪽은 모자라서 용도마다 다른 기준을 뒀다.
조치 — 2단계 복제 정리와 절차
10.0.0.23 이 10.0.0.21 을 따라가는 구조를 바꿨다.
STOP SLAVE;
CHANGE MASTER TO MASTER_HOST='10.0.0.20', ...;
START SLAVE;
2단계를 두는 것 대신 CHANGE MASTER TO 로 원본을 직접 보게 하는 쪽을 골랐다. 이유는 원본 부담은 늘어도 구조가 단순해져서다.
바꾸기 전에 원본이 사본 넷을 감당하는지 확인했다.
SHOW STATUS LIKE 'Binlog_cache%';
SHOW PROCESSLIST;
원본이 죽었을 때 밟을 절차도 적었다.
원본이 죽으면
1. 사본1(21)의 복제 지연이 0인지 확인
2. 21 에서 STOP SLAVE; RESET SLAVE ALL;
3. 애플리케이션 쓰기 대상을 21 로 바꾼다
4. 나머지 사본을 21 을 보게 바꾼다
5. 옛 원본은 켜지 말고 조사한다
다섯째를 적은 것은 옛 원본이 살아나 쓰기를 받으면 데이터가 갈리기 때문이다.
시험 환경에서 한 번 해 보니 셋째에서 애플리케이션 설정 자리를 몰라 시간이 걸렸고 그것도 절차에 적었다.
정리
- 복제는 상태만 봐서는 전체 구조를 모른다
- 관련 장비를 전부 돌면서 본다
- 2단계 복제가 있으면 중간이 죽을 때 뒤도 멈춘다
- 구조에 장비 사양과 위치를 같이 적는다
- 사양이 낮은 사본은 더 밀리고 위치에 따라 남는 것이 갈린다
- 무엇이 무엇을 읽는지 적는다
- 어느 것이 죽으면 무엇이 안 되는지가 그 표로 갈린다
- 지연을 계속 보되 용도마다 다른 기준을 둔다
- 원본이 죽었을 때 절차를 적고 실제로 해 본다
- 해 보면 빠진 것이 나온다