클라우드

읽기 복제본, 나눠 읽으면 오래된 값을 읽는다

RDS 읽기 복제본은 원본의 변경을 비동기로 받는다.
저장에 성공했다는 응답을 받고 곧바로 복제본에서 읽으면, 아직 반영되지 않은 예전 값이 보일 수 있다.

이 글의 목차읽기 복제본은 원본을 따라가는 사본이다6
  1. 읽기 복제본은 원본을 따라가는 사본이다
  2. ‘비동기’⁠로 따라간다는 뜻
  3. 복제는 얼마나 늦고, 어떻게 확인하는가
  4. 어떤 조회를 원본으로 보낼까
  5. 이름이 비슷해 헷갈리는 Multi-AZ
  6. 처음 복제본을 붙인다면

서비스가 커지면 데이터베이스 한 대가 받는 조회가 점점 늘어난다.
RDS 콘솔에서 데이터베이스를 고르고 작업 메뉴를 열면 ‘읽기 전용 복제본 생성’⁠이 보인다.

조회 일부를 복제본으로 보내면 원본의 부담은 실제로 줄어든다.
다만 복제본에서 읽은 값이 원본과 항상 같지는 않다.

읽기 복제본은 원본을 따라가는 사본이다

읽기 복제본은 DB 인스턴스의 읽기 전용 사본이다.
앱의 조회 일부를 복제본으로 보내면 원본은 쓰기와 나머지 조회에 힘을 쓸 수 있다.

복제본을 만들 때 RDS는 원본의 스냅샷을 떠서 읽기 전용 인스턴스를 만든다.
그 뒤로는 데이터베이스 엔진의 복제 기능으로 원본의 변경을 계속 따라간다.

복제본은 따로 떨어진 DB 인스턴스다.
접속 주소인 엔드포인트가 따로 있고, 요금도 일반 인스턴스와 같은 방식으로 따로 나간다.
어떤 조회를 원본과 복제본 중 어디로 보낼지는 앱이 정해야 한다.

‘비동기’⁠로 따라간다는 뜻

RDS는 원본에 생긴 변경을 복제본에 비동기로 복사한다.
비동기는 원본이 복제본의 적용을 기다리지 않고 앱에 저장이 끝났다고 답한다는 뜻이다.
복제본은 그 뒤에 따라온다.

예를 들어 사용자가 프로필 이름을 ‘민수’⁠에서 ‘지수’⁠로 바꾼다.
원본은 새 이름을 저장하고 앱에 성공을 알린다.
앱이 곧바로 프로필을 다시 읽는데, 그 조회가 아직 변경을 받지 못한 복제본으로 가면 ‘민수’⁠가 돌아온다.

조회 대상에 따른 저장 직후 값 저장 직후 원본을 읽으면 새 값이 보이지만 복제 적용 전의 복제본은 이전 값을 돌려준다. 개념 도해 조회 대상에 따른 저장 직후 값 저장 직후 요청 경로 앱 요청 ① 저장 요청 ② 원본 반영 ③ 즉시 조회 ④ 복제본 읽기 반영 전 ⑤ 이전 값 복제 경로 비동기 전달 복제 적용 조회 대상별 값의 최신성 즉시 조회 복제 적용 완료선 원본 새 값 복제본 이전 값 새 값 저장 이후 시간 저장 직후 원본을 읽으면 새 값이 보이지만 복제 적용 전의 복제본은 이전 값을 돌려준다. SOSHIN · DEV NOTES
쓰고 나서 곧바로 읽으면 방금 쓴 것이 아직 도착하지 않았을 수 있다.

저장이 취소된 것은 아니다.
새 이름이 있는 원본과 예전 이름이 남은 복제본을 차례로 보았을 뿐이다.
요청 하나하나에는 오류가 없는데, 사용자에게는 저장이 안 된 것처럼 보인다.

저장한 직후에는 두 곳의 값이 다르고, 복제가 반영된 뒤에야 같아진다.

저장한 이름이 두 곳에 보이기까지

이름을 저장한 뒤 복제본에 반영되기까지를 두 단계로 나눠 보여 준다.

원본민수저장하는 곳
복제본민수나눠 읽는 곳

처음에는 두 곳 모두 ‘민수’⁠다. 원본에 ‘지수’⁠를 저장해도 복제본은 아직 ‘민수’⁠일 수 있다. 변경이 복제본에 적용되면 두 곳 모두 ‘지수’⁠를 보여 준다.

실제 서버 연결 없이 복제 순서만 보여 준다. 기다리는 길이는 실제 지연 시간을 뜻하지 않는다.

복제는 얼마나 늦고, 어떻게 확인하는가

데이터베이스는 변경을 트랜잭션이라는 묶음 단위로 처리한다.
원본의 최신 트랜잭션과 복제본이 마지막으로 적용한 트랜잭션 사이의 시간 차이를 복제 지연(replica lag)⁠이라고 한다.

RDS는 이 지연을 AWS의 모니터링 서비스인 CloudWatch에서 ReplicaLag 지표로 보여 준다.
계산 방식이 데이터베이스 엔진마다 달라서, 같은 숫자라도 엔진에 따라 뜻이 조금씩 다르다.

MariaDB를 예로 들면 ReplicaLag가 0이면 복제본이 원본을 따라잡은 상태이고, -1이면 복제가 지금 동작하지 않는 상태다.
-1을 ‘지연 없음’⁠으로 읽으면 안 된다.

적용 위치에 따른 복제 지연 복제 지연은 원본의 최신 트랜잭션과 복제본이 마지막으로 적용한 트랜잭션 사이의 시간이고, -1은 복제가 멈춰 그 시간을 잴 수 없는 상태다. 개념 도해 적용 위치에 따른 복제 지연 트랜잭션이 적용된 위치 원본 커밋 순서 복제본 순서대로 다시 적용 10:00:00 10:00:01 10:00:02 10:00:03 10:00:04 10:00:05 10:00:06 10:00:00 10:00:01 10:00:02 10:00:03 10:00:04 10:00:05 10:00:06 ① 원본의 최신 ② 마지막으로 적용 아직 적용 전 ③ 복제 지연 · 4초 ReplicaLag 값 · MariaDB 예 0 2 4 6 8 10 -1 초 복제 멈춤 따라잡음 4초 뒤처짐 지연 시간 · 0 이상 복제 지연은 원본의 최신 트랜잭션과 복제본이 마지막으로 적용한 트랜잭션 사이의 시간이고, -1은 복제가 멈춰 그 시간을 잴 수 없는 상태다. SOSHIN · DEV NOTES
위에서 잰 4초가 아래 숫자줄의 4에 놓이고, -1은 지연 시간의 범위 밖에 따로 떨어져 있다.

평소에는 지연이 짧아도 바쁜 순간에는 늘어난다.
복제본은 원본에서 일어난 변경을 받아 순서대로 다시 적용하는데, 이 적용이 밀리는 경우가 흔히 셋이다.

원본에 쓰기가 한꺼번에 몰릴 때, 복제본에서 무거운 조회가 자원을 오래 차지할 때, 한 트랜잭션이 데이터를 아주 많이 바꿀 때다.

두 번째 원인이 헷갈리기 쉽다.
무거운 통계 조회를 원본에서 떼어 복제본으로 보냈는데, 그 조회가 복제본의 자원을 오래 쓰면 변경을 적용하는 일이 밀린다.
보고서는 잘 나오는데 다른 화면의 데이터가 늦게 바뀌는 식이다.

어떤 조회를 원본으로 보낼까

모든 조회를 복제본으로 보내면 원본은 가장 가벼워진다.
그런데 결제 내역이나 방금 고친 프로필처럼 새 값이 바로 보여야 하는 화면이 있다.
이런 조회는 원본에서 읽게 한다.

통계 화면, 관리자용 보고서, 검색 목록처럼 잠깐 늦어도 괜찮은 조회는 복제본으로 보내기 좋다.
AWS도 업무 보고용 조회를 복제본에서 돌리는 것을 대표적인 쓰임으로 든다.

기준은 화면의 종류보다 직전 행동이다.
‘상세는 원본, 목록은 복제본’⁠처럼 나누면 빈틈이 생긴다.
사용자는 방금 추가한 항목이 목록에 바로 보이기를 기대하기 때문이다.

그래서 방금 쓴 사용자의 다음 조회만 잠깐 원본으로 보내는 방법을 많이 쓴다.
흔히 ‘쓴 값 바로 읽기(read-your-writes)‘라고 부른다.
자기가 쓴 값은 바로 보이고, 다른 사용자에게는 조금 늦게 보여도 되는 서비스에 잘 맞는다.

원본에서 읽는다고 모든 어긋남이 풀리지는 않는다.
저장이 끝나기 전에 조회가 먼저 출발하거나, 앱의 캐시가 옛 응답을 돌려주면 원본을 읽어도 결과가 어긋난다.
읽는 위치와 요청 순서를 함께 봐야 한다.

이름이 비슷해 헷갈리는 Multi-AZ

RDS에는 ‘복제’⁠가 들어가는 구성이 더 있다.
Multi-AZ 배포의 대기 인스턴스는 원본과 동기식으로 복제되지만 읽기 요청은 받지 않는다.
장애 대비용이라 조회를 나누는 데는 쓰지 못한다.

Multi-AZ DB 클러스터는 또 다르다.
쓰기 인스턴스 하나와 읽기 인스턴스 둘을 서로 다른 가용 영역에 두고, 읽기 인스턴스가 조회도 받고 장애 때 쓰기 역할도 넘겨받는다.
가용 영역(AZ)⁠은 한 리전 안에서 물리적으로 떨어진 데이터센터 구역이다.

Multi-AZ DB 클러스터의 복제 지연과 전환 RDS Multi-AZ DB 클러스터는 승격 전에 미적용 변경을 처리한다. 대기 범위는 엔진에 따라 다르다. 개념 도해 Multi-AZ DB 클러스터의 복제 지연과 전환 장애 조치 경로 ① 장애 감지 ② 미적용분 따라잡기 ③ 쓰기 승격 ④ 연결 전환 ⑤ 서비스 재개 미적용 변경 처리 시차와 전환 시간의 관계 전환 시간 장애 순간의 시차 승격·연결 기준 시간 전체 전환 시간 따라잡기 시간 시차 작음 시차 큼 RDS Multi-AZ DB 클러스터는 승격 전에 미적용 변경을 처리한다. 대기 범위는 엔진에 따라 다르다. SOSHIN · DEV NOTES
RDS Multi-AZ DB 클러스터에서는 미적용 변경을 처리한 뒤 승격한다. 기다리는 범위는 엔진에 따라 다르다.

이 클러스터에서는 복제 지연이 화면의 오래된 값으로 끝나지 않는다.
장애 조치 때는 밀린 변경을 먼저 적용한 뒤에야 새 쓰기 인스턴스를 올린다.
지연이 길수록 전환도 늦어진다.

AWS가 이 클러스터의 복제 지연 경보를 만드는 방법을 따로 안내하는 것도 그래서다.
일반 읽기 복제본을 하나 붙였다고 이런 자동 전환이 생기지는 않는다.

처음 복제본을 붙인다면

읽는 방법얻는 것감수할 점
쓴 직후에는 원본에서 읽기자기 변경을 바로 확인원본에 조회 부담이 남음
늦어도 되는 조회만 복제본으로원본의 조회 부담이 줄어듦복제본 반영이 늦을 수 있음
모든 조회를 복제본으로원본이 가장 가벼워짐방금 쓴 값이 안 보이는 화면이 생김

복제본을 붙이기 전에는 ‘방금 쓴 값을 바로 다시 읽는 화면’⁠이 어디인지부터 찾는다.
그 화면의 조회만 원본으로 보내도 나머지 조회는 대부분 복제본으로 나눌 수 있다.

붙인 뒤에는 ReplicaLag에 경보를 걸어 둔다.
평소보다 지연이 길어진 시각을 알면 그때 돌던 무거운 조회나 대량 쓰기를 찾아볼 수 있다.

소신을 상징하는 까마귀 목판화 일러스트
작성자소신 · Soshin

웹과 서버를 만들고, 개발하며 배운 것들을 글로 남깁니다.

좌우로 움직여 보세요