읽기 요청을 읽기 전용 복제본으로 전송

AWSBeginner
지금 연습하기

소개

주문 애플리케이션은 현재 읽기와 쓰기를 하나의 기본 데이터베이스로 보냅니다. PostgreSQL 읽기 전용 복제본을 만들고 쿼리를 전달한 뒤 기본 데이터베이스의 새 쓰기가 복제본에서 읽히며 복제본은 쓰기를 거부함을 확인합니다.

데이터베이스 연결, SQL, 복구 실습 이후의 선택 확장입니다. 환경은 기본 데이터베이스와 예제 주문 세 건으로 독립적으로 시작합니다. 마지막에 복제본과 기본 데이터베이스를 삭제합니다.

자격증 시험과의 연관성

이 실습은 다음 시험 주제를 위한 기초 실습을 제공합니다.

읽기 전용 복제본 생성 및 확인

이 단계에서는 기본 데이터베이스의 변경을 받는 두 번째 PostgreSQL 인스턴스를 만듭니다.

읽기 전용 복제본은 복사된 데이터로 쿼리에 응답합니다. PostgreSQL은 **미리 쓰기 로그(WAL)**를 통해 변경을 보냅니다. 대기 서버는 변경을 재생합니다. 복제본은 별도의 엔진이며 방금 커밋된 쓰기보다 복제가 지연될 수 있습니다.

읽기 전용 복제본과 Multi-AZ 대기 인스턴스는 목적이 다릅니다. 복제본은 애플리케이션 쿼리용 읽기 엔드포인트를 제공합니다. 표준 Multi-AZ DB 인스턴스 배포의 대기 인스턴스는 가용성과 장애 조치를 지원하며 애플리케이션 읽기는 처리하지 않습니다. 이 실습은 복제본을 구현하며 Multi-AZ 장애 조치는 수행하지 않습니다.

준비된 연결 설정을 불러옵니다.

cd /home/labex/project
source database.env

소스를 확인합니다.

aws rds \
  describe-db-instances \
  --db-instance-identifier orders-db \
  --query 'DBInstances[0].{Identifier:DBInstanceIdentifier,Status:DBInstanceStatus,BackupRetention:BackupRetentionPeriod,Endpoint:Endpoint}'

RDS 읽기 전용 복제본 소스는 0이 아닌 백업 보존 기간이 필요합니다. 이 단원은 보존 기간 1로 설정된 기본 데이터베이스를 제공합니다. 준비된 소스 설정을 사용하며 자동 백업 스케줄은 테스트하지 않습니다.

복제본을 만듭니다.

aws rds \
  create-db-instance-read-replica \
  --db-instance-identifier orders-reader \
  --source-db-instance-identifier orders-db \
  --db-instance-class db.t3.micro \
  --no-publicly-accessible \
  --query 'DBInstance.{Identifier:DBInstanceIdentifier,Source:ReadReplicaSourceDBInstanceIdentifier,Status:DBInstanceStatus,Endpoint:Endpoint}'
aws rds \
  wait db-instance-available \
  --db-instance-identifier orders-reader

두 리소스를 확인합니다.

aws rds \
  describe-db-instances \
  --query 'DBInstances[].{Identifier:DBInstanceIdentifier,Source:ReadReplicaSourceDBInstanceIdentifier,Endpoint:Endpoint.Address}' \
  --output table

orders-reader의 별도 엔드포인트와 orders-db를 가리키는 소스 관계가 표시되어야 합니다. AWS View에는 기본 데이터베이스와 복제본이 표시됩니다.

실제 복제본 엔진을 조회합니다.

psql \
  "service=orders-reader" \
  --command 'SELECT current_database(), pg_is_in_recovery();'

데이터베이스 orders와 t(true)인 pg_is_in_recovery가 표시되어야 합니다. RDS 리소스에 복제본 표시만 있는 것이 아니라 PostgreSQL이 실제 대기 복구 모드로 실행됩니다.

애플리케이션 읽기 및 쓰기 엔드포인트 분리

이 단계에서는 쓰기를 기본 데이터베이스에 유지하고 쿼리를 복제본으로 보냅니다.

애플리케이션 설정을 확인합니다.

쓰기는 기본 DB로 보내고 읽기는 비동기 갱신 복제본을 사용할 수 있음

개념도: 쓰기는 기본 DB로 보내고 읽기는 비동기 갱신 복제본을 사용할 수 있음.

cat app-config.json

현재 두 호스트 필드는 기본 데이터베이스를 가리킵니다. 복제본 엔드포인트를 가져옵니다.

READER_ENDPOINT=$(aws rds \
  describe-db-instances \
  --db-instance-identifier orders-reader \
  --query 'DBInstances[0].Endpoint.Address' \
  --output text)

read_host만 변경합니다.

jq \
  --arg host "$READER_ENDPOINT" \
  '.read_host = $host' \
  app-config.json > app-config.new
mv app-config.new app-config.json

애플리케이션을 통해 읽습니다.

curl \
  --silent \
  --show-error \
  --fail \
  http://127.0.0.1:8080/application/orders | jq

원래 주문 세 건과 read_only: true가 표시되어야 합니다. 응답은 애플리케이션이 대기 서버에 맺은 실제 SQL 연결에서 나옵니다. AWS View에는 읽기 전용 복제본이 애플리케이션 데이터 소스로 표시됩니다.

복제본은 소스에서 복사된 데이터베이스 계정을 사용합니다. 엔드포인트 선택은 연결할 인스턴스를 정하며 데이터베이스 인증과 SQL 권한은 계속 적용됩니다.

복제 관찰 및 복제본 쓰기 거부

이 단계에서는 기본 데이터베이스를 통해 새 주문을 저장하고 복제본에서 읽습니다.

애플리케이션으로 주문을 추가합니다. POST 처리기는 여전히 기본 데이터베이스를 가리키는 write_host를 사용합니다.

curl \
  --silent \
  --show-error \
  --fail \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{"order_id":104,"customer":"Kai","total":"5.00"}' \
  http://127.0.0.1:8080/application/orders

saved: true가 표시되어야 합니다. 소스와 복제본을 별도로 조회합니다.

psql \
  "service=orders-db" \
  --command 'SELECT order_id, customer, total FROM orders WHERE order_id = 104;'
psql \
  "service=orders-reader" \
  --command 'SELECT order_id, customer, total FROM orders WHERE order_id = 104;'

둘 다 Kai의 5.00 주문이 표시되어야 합니다. 첫 복제본 쿼리에 행이 없다면 잠시 뒤 같은 쿼리를 반복하세요. 비동기 복제에는 지연이 있을 수 있습니다. 읽기 중심 작업에 유용하지만 즉각적인 일관성이 필요하면 방금 쓴 값을 기본 데이터베이스에서 읽어야 할 수 있습니다.

애플리케이션 목록을 다시 읽습니다.

curl \
  --silent \
  --show-error \
  --fail \
  http://127.0.0.1:8080/application/orders | jq

주문 네 건과 read_only: true가 표시되어야 합니다.

복제본에 실제 삽입을 시도합니다.

psql \
  "service=orders-reader" \
  --set=ON_ERROR_STOP=1 \
  --command "INSERT INTO orders (order_id, customer, total) VALUES (105, 'Lena', 9.00);"

읽기 전용 트랜잭션에서는 INSERT를 실행할 수 없다는 오류가 표시되어야 합니다. 복구 모드는 데이터베이스 마스터 계정의 쓰기도 거부합니다. 시도한 주문이 어느 엔진에도 없는지 확인합니다.

psql \
  "service=orders-db" \
  --command 'SELECT count(*) FROM orders WHERE order_id = 105;'
psql \
  "service=orders-reader" \
  --command 'SELECT count(*) FROM orders WHERE order_id = 105;'

각각 0이 표시되어야 합니다. 쓰기는 기본 데이터베이스에서 수행하고 일관성 요구가 허용하면 쿼리는 복제본을 사용합니다. 애플리케이션이 읽기 전용 복제본에서 원래 주문과 복제된 새 주문을 읽습니다.

복제본과 기본 데이터베이스 삭제

이 단계에서는 두 연습용 데이터베이스 인스턴스를 삭제합니다.

먼저 복제본을 삭제한 뒤 소스를 삭제합니다.

aws rds \
  delete-db-instance \
  --db-instance-identifier orders-reader \
  --skip-final-snapshot \
  --query 'DBInstance.DBInstanceIdentifier'
aws rds \
  wait db-instance-deleted \
  --db-instance-identifier orders-reader
aws rds \
  delete-db-instance \
  --db-instance-identifier orders-db \
  --skip-final-snapshot \
  --query 'DBInstance.DBInstanceIdentifier'
aws rds \
  wait db-instance-deleted \
  --db-instance-identifier orders-db
aws rds \
  describe-db-instances \
  --query 'DBInstances[].DBInstanceIdentifier'

[]가 표시되고 AWS View에 데이터베이스가 없어야 합니다. 준비된 애플리케이션과 네트워크 리소스는 유지하세요.

요약

PostgreSQL 읽기 전용 복제본을 만들고 실제 대기 복구 모드를 확인했습니다. 읽기·쓰기 엔드포인트를 분리하고 기본 데이터베이스의 새 쓰기가 복제본에 도달하는 것과 직접 쓰기 거부를 확인했습니다. 마지막에 둘 다 삭제했습니다.

읽기 전용 복제본은 읽기 접근 패턴을 지원하며 표준 Multi-AZ DB 인스턴스 배포의 대기 인스턴스와 목적 및 동작이 다릅니다. 마지막 챌린지에서 배운 연결 및 진단 기술을 적용합니다.