Cloud Modernization 15
RDS Multi-AZ, 읽기 전용 복제본, Aurora 클러스터: '복제'의 진짜 의미 파헤치기
복제라는 단어가 같아서 Multi-AZ와 읽기 전용 복제본이 모두 성능 확장용처럼 보인다.
근거 · 교안 p57-p61
1장: Multi-AZ: 고가용성을 위한 복제, 성능 확장은 NO
솔라의 손가락이 노트북 트랙패드 위에서 잠시 멈칫했다. 화면에는 AWS 데이터베이스 설정 창이 떠 있었다. ‘Multi-AZ deployment’라는 체크박스 옆에 붙은 작은 물음표 아이콘 위로 커서가 올라가자, ‘향상된 가용성 및 내구성을 위해 다른 가용 영역(AZ)에 예비 복제본을 생성합니다’라는 설명이 나타났다.
“복제본….”
솔라는 나직이 읊조렸다. 이 단어가 솔라의 머릿속에 하나의 그림을 그렸다. 똑같은 데이터를 가진 데이터베이스 서버가 하나 더 생기는 모습. 그렇다면 사용자의 요청을 둘로 나눌 수 있다는 뜻이 아닐까? 한쪽 서버에 쓰기(write) 요청이 집중될 때, 다른 쪽 서버는 읽기(read) 요청을 전담 처리하는 식으로 말이다. 성능을 높일 아주 간단하고 확실한 방법처럼 보였다.
“언니, 이것 봐. 되게 좋은 거 찾았어.”
솔라는 의자를 돌려 거실 소파에 앉아 있던 루나를 불렀다.
“DB 설정하는데, Multi-AZ 옵션을 켜면 데이터베이스 복제본을 하나 더 만들어 준대. 이제 서버가 두 개니까, 읽기 요청은 저쪽 복제본으로 싹 보내서 부하를 분산하면 되겠다! ‘복제’라고 하니까 데이터도 완전히 똑같을 거고, 완벽하잖아?”
자신의 발견이 자랑스럽다는 듯 솔라의 목소리가 들떴다. 루나는 잠시 솔라의 화면을 들여다보더니, 조용히 고개를 끄덕였다.
“복제본이라는 단어만 보면 그렇게 생각하기 쉽지. 그 복제본이 평소에 뭘 하고 있을지 상상해 본 적 있어?”
“뭘 하긴, 당연히 읽기 요청을 처리하고 있겠지? 가만히 놀게 두는 건 낭비잖아.”
솔라는 즉답했다. 그건 너무나 당연한 결론이었다. 루나는 말없이 자리에서 일어나 부엌으로 향하더니, 똑같이 생긴 유리컵 두 개를 들고 왔다. 하나는 솔라의 책상 오른쪽에, 다른 하나는 왼쪽에 놓았다.
“오른쪽이 우리가 원래 쓰던 메인 데이터베이스라고 하자. 그리고 왼쪽은 Multi-AZ로 생긴 ‘예비 복제본’이야.”
루나는 오른쪽 컵을 살짝 들어 보였다.
“사용자가 글을 쓰거나, 상품을 주문하거나, 댓글을 달면 데이터가 바뀌지. 그 모든 요청은 이 메인 DB로 와. 그리고 Multi-AZ를 켰으니까, 데이터가 바뀔 때마다 메인 DB는 이 예비 복제본한테 ‘나 지금 이렇게 데이터가 바뀌었어’라고 즉시 알려줘. 예비 복제본은 그 데이터를 받아서 자기 자신을 똑같이 업데이트하고.”
“응, 그게 동기화, 복제잖아. 그러니까 둘의 데이터는 항상 같을 거고. 그래서 내가 읽기 요청을 왼쪽 컵, 그러니까 예비 복제본으로 보내도 된다는 거였어.”
솔라는 루나의 비유에 자신의 논리를 다시 한번 덧붙였다.
“좋아. 그럼 최악의 상황을 한번 상상해 보자.”
루나가 말했다.
“어느 날 갑자기, 이 메인 DB가 있는 데이터 센터에 정전이 나거나 네트워크가 끊겼어. 아니면 그냥 서버 자체에 심각한 오류가 생겼거나.”
루나는 오른쪽 컵을 들더니, 바닥에 떨어져 산산조각 나는 시늉을 했다.
“메인 DB가 완전히 멈췄어. 그럼 우리 서비스는 어떻게 될까?”
“어… 그럼 서비스도 멈추겠지. 데이터베이스에 접속이 안 되니까.”
“Multi-AZ를 쓰는 이유가 바로 그 순간을 막기 위해서야. 메인 DB에 문제가 생겼다는 걸 감지하는 순간, 시스템은 모든 트래픽의 방향을 자동으로 예비 복제본 쪽으로 돌려버려. 그리고 이 예비 복제본을 새로운 메인 DB로 승격시키는 거지. 이 모든 과정이 몇 분 안에, 아주 빠르게 일어나.”
루나는 왼쪽 컵을 책상 중앙으로 옮기며 말했다.
“이제 이게 우리의 새로운 메인 DB가 되는 거야. 사용자는 아주 잠깐의 끊김을 느낄 수는 있어도, 서비스가 완전히 중단되지는 않아.”
솔라는 잠시 말이 없었다. 루나가 옮겨 놓은 왼쪽 컵과, 원래 오른쪽 컵이 있던 빈자리를 번갈아 보았다. 머릿속에서 뭔가 ‘아, 하는’ 느낌이 스쳤다.
“잠깐만… 만약에 내가 생각한 것처럼 예비 복제본이 평소에 내 읽기 요청들을 처리하느라 바빴다면?”
솔라가 스스로에게 묻듯 말했다.
“만약 예비 복제본이 이미 수많은 읽기 요청을 처리하느라 정신이 없었다면, 메인 DB가 고장 났을 때 즉시 그 자리를 대신할 준비가 안 되어 있을 수도 있겠네. 메인 DB의 마지막 데이터 변경분을 아직 미처 다 반영하지 못했을 수도 있고, 갑자기 쓰기 요청까지 받기 시작하면 과부하가 걸릴 수도 있고.”
생각이 꼬리를 물자 결론은 명확해졌다.
“아…! 그럼 저 예비 복제본은 그냥 비상 대기조구나. 평소에는 아무 일도 안 하고, 그냥 계속 데이터만 똑같이 받아놓고 있다가, 원래 있던 메인 DB한테 무슨 일이 생기면 바로 그 자리를 대신하는 거네. 성능을 위해서가 아니라, 서비스가 멈추지 않게 하려고.”
솔라의 얼굴에 놀라움과 깨달음이 교차했다. 예비 복제본이 아무 일도 안 하고 ‘놀고 있는’ 게 낭비가 아니었다. 그 ‘대기’ 자체가 예비 복제본의 가장 중요한 임무였던 것이다.
“바로 그거야. 그걸 ‘고가용성(High Availability)’이라고 불러. 성능 향상이 아니라 장애 상황에서도 서비스를 계속 유지하는 능력. 그래서 Multi-AZ의 복제는 메인 DB가 데이터를 쓰면, 예비 복제본이 ‘나도 받았어’라고 응답할 때까지 기다리는 ‘동기식’으로 작동해. 그래야 둘의 데이터가 1초의 오차도 없이 똑같이 유지되고, 언제든 서로를 대체할 수 있으니까.”
루나의 설명에 솔라는 고개를 끄덕였다. ‘복제’라는 같은 단어가 전혀 다른 목적을 위해 쓰이고 있었다. 성능 확장의 도구가 아니라, 장애 극복을 위한 비상 보험이었던 셈이다. 처음에 가졌던 흥분은 가라앉았지만, 대신 훨씬 명확한 그림이 머릿속에 자리 잡았다.
그러자 풀리지 않은 원래의 질문이 다시 떠올랐다.
“알겠어. Multi-AZ는 장애 대비용 보험 같은 거구나. 그럼 내가 진짜로 원했던 거, 그러니까 사용자가 많아져서 읽기 요청이 폭주할 때 성능을 높이는 건… 그건 어떻게 하는 거지? ‘복제’를 쓰는 다른 방법이 있는 건가?”
2장: 읽기 전용 복제본: 진짜 읽기 성능 확장
솔라는 다시 노트북 화면에 집중했다. 이전의 흥분은 가라앉았지만, 풀리지 않은 질문이 남긴 호기심이 그 자리를 채웠다. Multi-AZ가 장애 대비용 보험이라는 것은 확실히 이해했다. 책상 위에는 루나가 비유에 사용했던 두 개의 유리컵이 그대로 놓여 있었다. 하나는 책상 중앙에, 다른 하나는 조금 떨어진 곳에. 비상 대기조의 개념을 명확하게 보여주는 배치였다.
솔라의 손가락은 ‘읽기 전용 복제본 생성(Create read replica)’이라는 버튼 위를 맴돌았다. 설명에는 ‘읽기 중심의 워크로드 처리를 위해 수평으로 확장’이라는, 바로 자신이 원했던 기능이 적혀 있었다. ‘이거다!’ 싶었지만, 조금 전의 실수가 떠올라 섣불리 결론 내리지 않았다.
‘이것도 복제본인데… Multi-AZ의 예비 복제본과는 뭐가 다른 거지? 그냥 평소에 읽기 요청을 허용하는 것 말고 근본적인 차이가 있는 걸까?’
솔라는 고민 끝에 부엌으로 가 종이컵 세 개를 가져왔다. 그리고는 메인 DB를 상징하는 중앙의 유리컵 옆에 나란히 놓았다. 갑자기 늘어난 컵들을 본 루나가 흥미로운 표정으로 다가왔다.
“새로운 실험 준비야?”
“응. 이게 내가 진짜 원했던, 읽기 성능을 높이는 방법인 것 같아서. ‘읽기 전용 복제본’이래. 이 종이컵들이 그 복제본들이라고 치는 거야. 이제 사용자들이 글을 읽는 요청은 이쪽으로 보내면 되는 거 맞지?”
솔라는 자신만만하게 말하면서도 루나의 반응을 살폈다. 이번에야말로 정답이길 바라는 마음이었다.
“맞아. 그게 읽기 전용 복제본의 주된 용도지. 그런데 한 가지 중요한 차이가 있어. Multi-AZ의 예비 복제본과 이 읽기 전용 복제본들이 메인 DB의 데이터를 받아 가는 방식 말이야.”
루나는 메인 DB를 상징하는 유리컵을 들었다.
“아까 Multi-AZ는 메인 DB에 데이터가 바뀔 때, 예비 복제본이 ‘나도 받았어’라고 응답할 때까지 기다린다고 했지? 그걸 동기식 복제라고 했고.”
루나는 이번엔 메인 유리컵에 물을 조금 붓는 시늉을 하더니, 즉시 다른 행동을 취하지 않고 옆에 있던 예비 복제본 컵을 가만히 바라봤다. 마치 응답을 기다리는 것처럼.
“하지만 읽기 전용 복제본은 그렇게 작동하지 않아. 상상해 봐. 우리 쇼핑몰에 갑자기 유명인이 방문해서 ‘이 상품 정말 좋아요!’라는 글을 남겼어. 그 순간 수천, 수만 명의 사람들이 상품 페이지를 보려고 몰려들겠지. 그 모든 읽기 요청을 처리하기 위해 우리는 읽기 전용 복제본을 5개나 준비해 뒀어.”
루나는 솔라가 가져온 종이컵들을 가리켰다.
“그런데 바로 그때, 다른 사용자가 상품 후기를 하나 더 작성했어. 이건 데이터 변경, 즉 ‘쓰기’ 요청이지. 이 요청이 메인 DB로 갔어. 만약 이 복제본들이 모두 ‘변경 내용 다 받았어요!’라고 응답할 때까지 메인 DB가 기다려야 한다면 어떻게 될까?”
솔라의 눈이 커졌다.
“그럼… 후기 하나 쓰는 데 한참 걸리겠네. 복제본이 5개면 5곳에서 모두 응답이 올 때까지 글쓰기 작업이 끝나지 않는 거니까. 복제본이 많아질수록 쓰기 작업은 점점 더 느려지겠구나.”
“바로 그거야. 읽기 성능을 높이려고 복제본을 늘렸는데, 정작 가장 중요한 쓰기 성능이 엉망이 되는 거지.”
솔라는 자신이 놓치고 있던 핵심을 깨달았다. 읽기 확장의 목적을 달성하려면, Multi-AZ와는 전혀 다른 방식의 복제가 필요했다.
“아…! 그럼 읽기 전용 복제본은 메인 DB를 기다리게 하면 안 되는 거네. 메인 DB는 그냥 ‘데이터 바뀌었어!’라고 외치기만 하고 자기 할 일을 계속해야 해. 복제본들은 그 소리를 듣고 각자 알아서 데이터를 가져가는 거고.”
“정확해. 메인 DB는 복제본들이 데이터를 받아 갔는지 확인하거나 기다리지 않아. 이걸 ‘비동기식 복제’라고 불러. 그래서 쓰기 작업에 거의 영향을 주지 않으면서 읽기 성능을 수평으로 확장할 수 있는 거야.”
루나는 메인 유리컵에서 종이컵들로 물을 옮겨주는 대신, 마치 메인 컵에서 데이터가 흘러나와 각 종이컵으로 자연스럽게 스며드는 듯한 손짓을 해 보였다. ‘기다림 없는 전파’였다.
솔라는 고개를 주억거렸다. 머릿속에 두 개의 명확한 그림이 그려졌다.
하나는 메인 DB와 예비 복제본이 서로 손을 꽉 잡고 한 걸음씩 같이 나아가는 모습이었다. 한쪽이 넘어지면 다른 쪽이 즉시 부축할 수 있도록. 이것이 고가용성을 위한 동기식 복제였다.
다른 하나는 메인 DB가 연단 위에서 확성기로 외치면, 청중석에 앉은 여러 복제본들이 각자 노트를 받아 적는 모습이었다. 청중 몇 명이 잠시 졸거나 딴짓을 해서 한두 단어를 놓칠 수도 있지만(아주 짧은 시간 데이터가 일치하지 않을 수 있지만), 연설의 흐름(쓰기 성능)은 전혀 방해받지 않았다. 이것이 읽기 확장을 위한 비동기식 복제였다.
“이제 알겠어. ‘복제’라는 말은 같지만, 목적에 따라 방법이 완전히 다른 거구나. Multi-AZ는 데이터 손실을 0으로 만들기 위한 ‘안정성’ 중심, 읽기 전용 복제본은 쓰기 성능을 방해하지 않으면서 읽기 부하를 분산하기 위한 ‘확장성’ 중심.”
솔라는 마침내 자신이 처음 가졌던 질문의 답을 스스로 찾아냈다. 하지만 화면의 다른 한구석에 있던 단어가 눈에 들어오자 새로운 궁금증이 고개를 들었다.
“언니, 그럼 이건 뭐야? Amazon Aurora. 설명에 ‘MySQL 및 PostgreSQL과 호환되는 고성능 관계형 데이터베이스… 클러스터…’ 라고 되어 있는데. 이건 Multi-AZ랑 읽기 전용 복제본을 합쳐 놓은 더 좋은 버전 같은 건가? 아니면 또 완전히 다른 세상의 이야기인 걸까?”
3장: Aurora 클러스터: 분산 스토리지 혁신과 새로운 확장성
솔라의 책상 위에는 이제 여러 개의 컵이 어지럽게 놓여 있었다. 고가용성을 상징하는 유리컵 한 쌍, 읽기 확장을 위한 종이컵 여러 개. 이 작은 모형들은 ‘복제’라는 단어 뒤에 숨은 두 가지 다른 세계를 명확히 보여주고 있었다. 솔라는 만족스러운 미소를 지으며 자신의 노트북 화면으로 다시 눈을 돌렸다. 하지만 ‘Amazon Aurora’라는 이름이 자꾸만 눈에 밟혔다.
‘고성능… 클러스터…’ 설명에 나온 단어들이 머릿속을 맴돌았다. 솔라는 잠시 고민하더니, 깨끗한 노트를 한 장 꺼내 펜을 들었다. 말로만 생각하는 것보다 그림으로 그려보면 더 명확해질 것 같았다. 그녀는 방금 이해한 두 가지 개념을 합쳐보기 시작했다. 먼저 가운데에 ‘쓰기 DB(메인)’라고 적은 네모를 그렸다. 그 옆에는 점선으로 ‘예비 DB(Multi-AZ용)’를, 아래에는 실선으로 ‘읽기 DB 1’, ‘읽기 DB 2’를 여러 개 그렸다. 이것들을 화살표로 연결하고 보니 꽤 그럴듯한 시스템이 완성되었다.
“이거 아닐까?”
솔라는 자신의 그림을 보며 중얼거렸다. 고가용성을 위한 예비 DB와 읽기 확장을 위한 복제본들을 모두 가진, 그야말로 ‘완전체’ 데이터베이스. Aurora는 분명 이럴 것이라고, 솔라는 거의 확신했다. 마침 다가온 루나는 솔라의 노트에 그려진 복잡한 다이어그램을 흥미롭게 들여다보았다.
“오로라의 구조를 추리해 본 거야?”
“응. Multi-AZ의 장점인 고가용성이랑, 읽기 전용 복제본의 장점인 읽기 확장성을 다 합친 모델 같아서. 쓰기 DB 하나에, 장애 대비용 예비 DB도 있고, 읽기 요청을 처리할 복제본들도 잔뜩 있는 거지. 이 그림처럼.”
솔라의 설명에 루나는 고개를 끄덕였다. 하지만 그 표정은 ‘정답’이라고 말하는 것과는 미묘하게 달랐다. 루나는 솔라의 펜을 빌려, 그림 옆 빈 공간에 새로운 그림을 그리기 시작했다.
“그렇게 생각하는 게 자연스러워. 하지만 오로라는 단순히 기능을 합친 게 아니라, 생각의 출발점 자체가 달라. 우리는 지금까지 계속 DB 인스턴스, 즉 ‘컴퓨터’를 중심으로 생각했어. 이 컴퓨터, 저 컴퓨터에 데이터를 어떻게 복사할까 하고.”
루나는 먼저 바닥에 길고 커다란 직사각형을 그렸다. 그리고 그 안에 ‘공유 스토리지 볼륨 (Shared Storage Volume)’이라고 적었다.
“오로라의 핵심은 바로 이거야. ‘스토리지’ 그 자체. 기존 방식처럼 각각의 DB 인스턴스가 자기만의 디스크를 가지고 데이터를 복사하는 게 아니야. 처음부터 모든 데이터는 아주 똑똑하고, 튼튼하고, 거대한 하나의 저장소에 담겨 있어.”
루나는 그 거대한 스토리지 사각형 위에 작은 네모들을 여러 개 그렸다. 그리고 각각 ‘쓰기 인스턴스’, ‘읽기 인스턴스 1’, ‘읽기 인스턴스 2’ 라고 적었다. 중요한 것은, 이 작은 네모들에서 스토리지로 향하는 화살표가 ‘복사(copy)’가 아니라 ‘연결(connect)’처럼 보인다는 점이었다.
“여기 이 DB 인스턴스들은 이제 두뇌와 입, 귀 역할만 하는 거야. 계산(컴퓨팅)을 처리하고, 사용자의 요청을 읽고 쓰는 거지. 데이터 자체는 저 아래에 있는 공유 스토리지에 있어. 모든 인스턴스가 같은 데이터를 보고 있는 거야. 따로 복사할 필요 없이.”
솔라는 두 그림을 번갈아 보았다. 자신이 그린 그림은 여러 대의 컴퓨터가 각자의 하드디스크를 가지고 서로 데이터를 주고받는 모습이었다. 하지만 루나가 그린 그림은, 거대한 중앙 도서관(공유 스토리지)에 있는 책을 여러 명의 사서(DB 인스턴스)가 동시에 참조하는 모습에 가까웠다.
“잠깐만… 그럼 데이터를 복사하는 과정이 거의 없다는 거야? 그럼 읽기 전용 복제본을 만들 때, 그 많은 데이터를 다 복사할 필요 없이 그냥 이 공유 스토리지에 연결만 시켜주면 되는 거네? 그래서 그렇게 빨리 만들어지는 거구나!”
“맞아. 데이터 복제가 아니라, 그냥 스토리지에 접근할 수 있는 권한을 가진 인스턴스를 하나 더 추가하는 것에 가까우니까. 그리고 이 공유 스토리지 자체가 데이터를 여러 곳에 알아서 복제하고 관리해. 하나의 데이터 조각을 6개의 복사본으로 만들어서 3개의 다른 시설에 나눠서 저장하지. 그래서 설령 일부 디스크에 문제가 생겨도 데이터는 절대 사라지지 않고, 쓰기 작업도 중단되지 않아.”
솔라의 머릿속에서 모든 조각이 맞춰졌다. Multi-AZ와 읽기 전용 복제본은 기존 데이터베이스의 한계를 ‘어떻게 극복할까’라는 고민에서 나온 해법이었다. 동기식 복제로 안정성을, 비동기식 복제로 확장성을. 하지만 오로라는 문제의 판 자체를 바꾼 것이었다. ‘컴퓨터와 저장소를 분리하면 어떨까?’ 라는 근본적인 질문에서 시작된 완전히 새로운 설계였다.
“이제 알겠어. ‘복제’의 진짜 의미. Multi-AZ는 안정성을 위해 인스턴스 간에 데이터를 동기화하는 것이고, 읽기 전용 복제본은 확장성을 위해 비동기적으로 데이터를 퍼뜨리는 것이었어. 하지만 오로라는… 아예 스토리지 레벨에서 데이터의 안정성과 공유를 책임지는 거구나. 인스턴스들은 그냥 그 위에 올라타서 역할만 하면 되고.”
단순히 더 좋은 버전이 아니었다. 종의 기원이 다른 생물과 같았다.
솔라는 노트의 마지막 페이지를 폈다. 그리고는 깨끗한 표를 그리기 시작했다. 맨 위에는 ‘목표’, ‘Multi-AZ’, ‘읽기 전용 복제본’, ‘Aurora’라고 적었다. 그리고 첫 번째 행에 ‘고가용성(장애 극복)’이라고 쓴 뒤, 각 칸을 채워나갔다.
- Multi-AZ: 동기식 복제를 통해 Standby 인스턴스가 즉시 대체. (O)
- 읽기 전용 복제본: 주 목적이 아님. 수동 조치 필요. (△)
- Aurora: 공유 스토리지 기반으로 즉시 장애 조치 및 자동 복구. (◎)
두 번째 행에는 ‘읽기 성능 확장’이라고 적었다.
- Multi-AZ: Standby 인스턴스는 읽기에 사용 불가. (X)
- 읽기 전용 복제본: 비동기식 복제로 다수의 복제본 추가 가능. (O)
- Aurora: 공유 스토리지에 연결된 읽기 인스턴스를 최대 15개까지 초고속으로 추가 가능. (◎)
표를 완성한 솔라는 뿌듯한 표정으로 루나를 바라봤다. 이제 더 이상 ‘복제’라는 단어에 흔들리지 않을 자신이 있었다. 세 가지 기술은 경쟁 관계가 아니라, 각기 다른 문제와 목적을 위해 태어난, 저마다의 이유가 있는 도구들이었다. 이제 어떤 상황에 어떤 도구를 꺼내야 할지 명확하게 보였다.