페일오버
페일오버는 맡고 있던 일을 죽은 쪽에서 살아 있는 쪽으로 넘깁니다. 서버 한 대가 응답을 멈추면 옆에 세워 둔 다른 한 대가 그 몫을 이어받습니다. 새벽에 사람이 깨어나 손으로 갈아 끼우지 않아도 서비스가 이어집니다.
쉽고 빠른 이해
페일오버는 일하던 기계가 죽었을 때 그 일을 대신할 기계로 넘기는 전환입니다. 데이터베이스의 주 서버가 응답을 멈추면 복사본을 받아 두던 대기 서버가 주 서버 노릇을 이어받는 것이 그런 경우입니다.
이게 없으면 기계 한 대가 죽는 순간 서비스 전체가 멈춥니다. 사람이 알아채고 손으로 갈아 끼울 때까지 그대로 서 있게 됩니다.
어떻게 도나:
- 감시하는 쪽이 주 서버가 응답하는지 계속 살핍니다
- 정해 둔 시간 동안 답이 없으면 죽은 것으로 판정합니다
- 대기 서버를 주 서버로 올립니다. 그리고 손님이 찾아오는 길을 그쪽으로 돌립니다
대가가 있습니다. 놀고 있는 기계를 한 대 더 유지해야 합니다. 넘어가는 동안은 잠깐 서비스가 끊깁니다. 판정이 틀려 멀쩡한 서버를 죽었다고 보면 같은 일을 두 대가 동시에 하게 됩니다.
상세
이 편에서는 평소에 일을 맡고 있는 쪽을 「주 서버」, 넘겨받으려고 기다리는 쪽을 「대기 서버」라고 부르겠습니다. 살아 있는지 살피고 전환을 지시하는 쪽은 「감시자」입니다. 요청을 보내는 쪽은 「손님」입니다. 다른 서비스든 사람이 쓰는 앱이든 요청을 보내면 손님입니다.
영어로는 failover 라고 씁니다. 우리말로는 장애 조치라고도 부릅니다.
비유로 보는 페일오버
고속도로를 달리다 타이어가 터지면 차를 갓길에 세웁니다. 트렁크에는 쓸 일이 없기를 바라며 싣고 다닌 예비 타이어가 있습니다. 잭을 받치고 갈아 끼우는 동안 차는 서 있고, 다 끼우고 나면 다시 달립니다.
페일오버가 그 교체입니다. 무엇으로 갈아 끼울지, 언제 갈아 끼울지, 갈아 끼운 뒤에 터진 쪽은 어떻게 할지를 미리 정해 두는 일입니다.
한 대만 두면 생기는 문제
서버를 한 대만 두면 그 한 대가 곧 서비스입니다. 그 기계의 디스크가 깨지거나 전원이 나가면 서비스도 같이 멈춥니다. 혼자 죽어서 전체를 멈추는 이런 지점이 단일 장애점입니다.
없애는 방법은 같은 일을 할 것을 하나 더 두는 것입니다. 다만 하나 더 두는 것만으로는 모자랍니다. 죽은 쪽에서 살아 있는 쪽으로 일을 넘기는 절차가 같이 있어야 그 여분이 값을 합니다.
페일오버가 그 절차입니다. 장애가 나도 서비스가 이어지게 만드는 성질을 고가용성이라고 합니다. 페일오버는 그것을 이루는 주된 수단입니다.
넘겨줄 주인이 있을 때만 쓰는 말
한 번에 한 대만 맡을 수 있는 몫이 있습니다. 데이터베이스의 쓰기가 그런 몫입니다. 여러 대를 한 덩어리로 묶어 굴리는 것을 클러스터라고 합니다. 그중 한 대가 지시와 조율을 맡는 대표 노릇도 한 번에 한 대만 맡습니다.
주인이 하나뿐이라 그 하나가 죽으면 누군가 대신 주인이 되어야 합니다. 페일오버는 바로 그 주인 노릇을 넘기는 일입니다.
상태를 들고 있지 않은 서버에는 이 말을 잘 안 씁니다. 같은 서버 여러 대가 이미 나란히 일하고 있어서, 죽은 한 대를 목록에서 빼기만 하면 남은 대들이 그 몫을 받습니다. 넘겨줄 주인 노릇이 없기 때문입니다.
페일오버가 도는 순서
전환은 네 단계로 나뉩니다. 살피기, 판정, 승격, 길 돌리기입니다.
감시자는 주 서버가 살아 있는지 계속 확인합니다. 살아 있는 쪽이 짧은 신호를 일정한 간격으로 보내는 방법은 하트비트입니다. 감시자가 먼저 물어보고 답을 받는 방법은 헬스 체크입니다.
답이 한 번 없다고 바로 죽었다고 보지는 않습니다. 네트워크가 잠깐 막히기만 해도 신호는 늦습니다. 그래서 정해 둔 시간 동안 답이 없을 때 죽었다고 판정합니다. 이 기다리는 시간이 타임아웃입니다.
판정이 나면 대기 서버를 주 서버로 올립니다. 올리는 이 일을 승격이라고 합니다. 쓰기를 안 받던 서버가 쓰기를 받기 시작합니다. 주 서버만 하던 몫을 넘겨받습니다.
sequenceDiagram
participant 손님
participant 주서버
participant 감시자
participant 대기서버
손님->>주서버: 요청
주서버-->>손님: 응답
Note over 주서버: 여기서 멈춘다
감시자->>주서버: 살아 있나
Note over 감시자: 답이 없다. 기다리는 시간이 다 지난다
감시자->>대기서버: 주 서버가 되어라
Note over 대기서버: 읽기만 받던 상태를 풀고 쓰기를 받는다
손님->>대기서버: 요청
그림의 마지막 줄이 네 번째 단계입니다. 손님은 주소를 바꾼 적이 없습니다. 그런데 요청은 대기 서버로 갔습니다. 그 길을 누가 돌렸는지를 다음에서 봅니다.
새 주 서버를 찾아가는 길
손님이 붙는 곳은 기계가 아니라 주소입니다. 승격만 해 놓고 주소를 그대로 두면 손님은 여전히 죽은 서버를 두드립니다. 그래서 전환의 마지막은 언제나 길을 돌리는 일입니다.
길을 돌리는 방법은 셋입니다.
| 방법 | 어떻게 돌리나 | 곤란한 대목 |
|---|---|---|
| 떠다니는 주소 | 서버 사이를 옮겨 다니는 주소를 대기 서버가 넘겨받는다 | 같은 망 안에서만 옮길 수 있다 |
| 앞에 세운 중개자 | 손님은 중개자에게만 붙고, 중개자가 뒤에 둘 서버를 바꾼다 | 중개자 자신이 죽으면 그것도 넘겨야 한다 |
| 이름 기록 바꾸기 | 이름이 가리키는 주소를 새 서버 것으로 고친다 | 손님이 들고 있는 옛 주소가 사라질 때까지 기다린다 |
첫 줄에서 서버 사이를 옮겨 다니는 주소를 가상 IP라고 부릅니다. 둘째 줄의 중개자 자리에는 로드 밸런서나 리버스 프록시를 세웁니다. 세 번째 줄의 이름은 DNS(Domain Name System, 도메인 네임 시스템)가 주소로 바꿔 주는 이름입니다.
표의 마지막 칸이 셋의 공통점을 말합니다. 어느 방법을 쓰든 길을 돌리는 데 시간이 듭니다. 그 시간이 페일오버가 언제 끝나는지를 정합니다.
대기 서버의 준비 상태
대기 서버가 평소에 무엇을 하고 있느냐에 따라 전환이 빨라지기도 하고 느려지기도 합니다.
| 준비 상태 | 대기 서버가 평소에 하는 일 | 넘어가는 데 드는 시간 |
|---|---|---|
| 식은 대기 | 꺼져 있다. 필요할 때 켠다 | 켜고 데이터를 채우는 만큼 길다 |
| 따뜻한 대기 | 켜져 있고 복사본을 계속 받는다 | 승격과 길 돌리기만 하면 된다 |
| 뜨거운 대기 | 켜져 있고 읽기 요청까지 받는다 | 따뜻한 대기와 같고, 평소 부하도 나눠 진다 |
| 둘 다 주 서버 | 두 대가 모두 쓰기를 받는다 | 죽은 쪽 몫이 남은 쪽으로 몰릴 뿐이다 |
실무에서는 위 세 줄을 차례로 콜드 스탠바이·웜 스탠바이·핫 스탠바이라고 부릅니다. 마지막 줄처럼 두 대가 모두 쓰기를 받는 구성은 액티브-액티브입니다. 한 대만 쓰기를 받는 앞의 셋은 액티브-스탠바이입니다.
아래로 갈수록 전환이 짧아집니다. 그만큼 평소에 드는 값도 큽니다.
넘어가는 동안 잃는 것
페일오버는 두 가지를 잃습니다. 하나는 시간이고 하나는 데이터입니다.
시간은 판정까지 기다린 만큼에 승격과 길 돌리기에 든 만큼을 더한 것입니다. 그동안 들어온 요청은 실패하거나 밀립니다. 기다리는 시간을 짧게 잡으면 이 끊김이 줄지만 오판이 늘어납니다.
데이터는 복사가 얼마나 따라왔는지가 정합니다. 주 서버가 받은 쓰기를 대기 서버로 보내 같은 내용을 갖게 하는 일을 복제라고 합니다. 보내 놓고 도착 확인을 기다리지 않는 방식을 비동기 복제라고 합니다. 이때 주 서버가 죽으면 아직 못 건너간 쓰기가 사라집니다.
사라지는 쓰기 중에는 손님에게 이미 「됐습니다」라고 답한 것도 섞여 있습니다. 답을 보내는 때와 복제가 건너가는 때가 달라서 생기는 일입니다.
sequenceDiagram
participant 손님
participant 주서버
participant 대기서버
손님->>주서버: 쓰기
주서버-->>손님: 됐습니다
주서버->>대기서버: 복제를 보낸다
Note over 주서버: 여기서 멈춘다. 복제가 아직 안 건너갔다
Note over 대기서버: 승격된다. 방금 그 쓰기가 없다
손님이 「됐습니다」를 받은 것은 두 번째 줄입니다. 복제는 그 뒤에 출발했고 건너가지 못했습니다. 그래서 승격된 대기 서버에는 그 쓰기가 없습니다.
확인을 받고 나서 답하는 동기 복제로 바꾸면 이 유실을 막습니다. 대신 쓰기마다 대기 서버까지 다녀오는 시간이 붙습니다.
멀쩡한 서버를 죽었다고 볼 때
판정은 어디까지나 추측입니다. 주 서버가 멀쩡한데 감시자에게 가는 길만 막혀도 답은 끊깁니다. 네트워크가 갈라져 서로 못 보게 된 상태가 분단입니다.
이때 대기 서버를 올리면 주 서버가 둘이 됩니다.
flowchart TD
subgraph s1["끊긴 이쪽"]
손님A["손님 A"] -->|쓰기| 주서버["주 서버"]
end
subgraph s2["끊긴 저쪽"]
감시자 -->|주 서버가 되어라| 대기서버["대기 서버"]
손님B["손님 B"] -->|쓰기| 대기서버
end
감시자 -. 살아 있나 · 길이 막혔다 .-> 주서버
감시자가 못 보는 것은 주 서버뿐입니다. 손님 A 는 여전히 주 서버에 쓰고 있습니다. 양쪽이 서로 다른 쓰기를 받아 데이터가 갈라지는 이 사고를 스플릿 브레인이라고 합니다. 복구가 까다로운 상태입니다. 갈라진 두 벌을 사람이 하나씩 대조해 맞춰야 합니다.
막는 방법은 둘입니다. 하나는 과반이 동의할 때만 승격을 허용하는 것입니다. 이 과반이 정족수입니다.
다른 하나는 승격하기 전에 옛 주 서버가 더는 쓰지 못하게 확실히 끊어 두는 것입니다. 이것을 펜싱이라고 부릅니다.
돌아온 서버와 페일백
고쳐서 돌아온 서버에는 두 갈래가 있습니다. 그대로 대기 서버로 두는 것과 다시 주 서버로 되돌리는 것입니다. 되돌리는 쪽이 페일백입니다.
stateDiagram-v2
state "주 서버" as 주
state "응답이 끊긴 상태" as 끊김
state "대기 서버" as 대기
[*] --> 주
주 --> 끊김: 응답이 끊긴다
끊김 --> 대기: 고쳐서 돌아온다
대기 --> 주: 페일백 · 되돌린다
대기 --> 대기: 다음 장애 때까지 그대로 둔다
그림이 보이듯 한 기계가 세 상태를 돌아다닙니다. 페일백은 이 고리를 한 바퀴 더 도는 일입니다. 되돌리는 것도 전환이라 그만큼 또 끊깁니다.
그래서 돌아온 서버를 대기 서버로 두고 다음 장애 때 다시 넘기는 쪽을 고르는 경우가 많습니다. 그림에서 대기 서버에 걸린 자기 화살표가 그 갈래입니다.
저절로 되돌리게 해 두면 하나가 더 걸립니다. 장애가 오락가락하는 서버는 넘겼다 되돌렸다를 되풀이하게 됩니다. 그 사이 서비스는 계속 끊깁니다. 이 되풀이가 플래핑입니다.
자동 전환과 수동 전환
전환을 감시자에게 맡기면 사람이 깨어나기 전에 끝납니다. 대신 오판까지 저절로 실행됩니다.
사람이 하면 오판을 걸러 낼 수 있습니다. 대신 연락이 닿고 접속해서 명령을 내릴 때까지 서비스가 멈춰 있습니다.
그래서 중간을 고르기도 합니다. 감시자가 판정과 준비까지만 해 두고 마지막 승격 명령은 사람이 누르는 방식입니다. 어느 쪽으로 갈지는 멈춰 있는 값과 잘못 넘어가는 값 가운데 무엇이 더 비싼지가 정합니다.
관련 항목
페일오버가 지키려는 성질
고가용성 · 단일 장애점 · 다중화 · 내결함성 · 재해 복구 · 평균 복구 시간 · 서비스 수준 목표
주 서버가 죽었는지 알아내는 살핌 수단
하트비트 · 헬스 체크 · 장애 감지 · 타임아웃 · 모니터링 · 워치독
전환에 참여하는 서버 역할
프라이머리 · 스탠바이 · 콜드 스탠바이 · 웜 스탠바이 · 핫 스탠바이 · 레플리카 · 노드 · 클러스터 · 액티브-스탠바이 · 액티브-액티브
전환을 실행하는 절차
승격 · 페일백 · 리더 선출 · 펜싱 · 펜싱 토큰 · 정족수 · 리스
데이터를 대기 서버로 옮기는 방법
복제 · 동기 복제 · 비동기 복제 · 복제 지연 · 스냅샷 · 체크포인트
손님을 새 주 서버로 잇는 중개 장치
가상 IP · 로드 밸런서 · DNS · 리버스 프록시 · 커넥션 풀
페일오버가 잘못될 때 나는 사고
다른 이름: failover · fail-over · 장애 조치 · 장애 극복 · 자동 전환