loading...

MSA 환경에서 데이터 관리를 위한 필수사항
- 고가용성과 데이터 동기화

MSA 환경에서 데이터 관리를 위한 필수사항 - 고가용성과 데이터 동기화

들어가며

디지털 혁신의 시대에 접어들면서 데이터는 기업의 중요한 자산이 되었습니다. 데이터의 위상이 높아진 것만큼이나 IT 아키텍처에 대한 인식에도 많은 변화가 생겼습니다. 기업들이 기민한 고객 대응을 위해 MSA(Microservices Architecture, 마이크로서비스 아키텍처)를 선호하는 최근의 추세가 이를 증명합니다. 그런데 MSA는 데이터를 분산시켜 정합성 유지에 어려움을 유발합니다. 그렇다면 MSA 환경에서 데이터 관리는 어떻게 해야 할까요?

본 아티클에서는 수년간 MSA 구조의 시스템을 다루어 온 필자의 경험을 바탕으로 IT 개발자 및 운영관리자가 염두에 두어야 할 MSA에서의 데이터 관리 방안에 대해 살펴보겠습니다.

MSA로 시스템을 구축한 후 단위 서비스별로 DB 간에 공유되어야 할 데이터가 일치하지 않는(틀어진) 경우를 꽤 발견할 수 있습니다. 수년 전부터 일치하지 않은 상태로 관리되어 온 데이터를 우연히 발견하면 로그나 추적할 정보가 전혀 남아있지 않다 보니 상당한 고민거리로 작용합니다. 불일치가 더 심해진 건 아닌지 파악해보고 싶은데 실시간 데이터 변경이 일어나는 상황에서 정합성을 맞춰보는 것도 쉬운 일이 아닙니다. 그렇다고 일치하지 않는 데이터가 발견될 때마다 수동으로 맞추는 것도 한계가 있습니다.

왜 이런 상황이 발생할까요? 단순한 버그 문제일 수도 있고 아키텍처 설계가 잘못되었기 때문일 수도 있습니다. 버그는 소프트웨어 품질 이슈로 고칠 수 있지만 한 번 구성한 시스템의 아키텍처를 손보는 것은 여간 어려운 일이 아닙니다. 결국 원인을 분석해보면 기본에 충실하지 않은 아키텍처 설계 때문으로 나타나는 경우가 꽤 많습니다. 여기서 말하는 "기본에 충실하다"는 것은 "엔터프라이즈 시스템은 고가용성(High Availability, HA)을 전제로 해야 한다"는 사실입니다. 트랜잭션의 99% 이상은 당연히 정상적으로 처리되어야 합니다. 극히 일부분의 거래가 실패하는데 이 처리에 얼마나 공을 들였느냐에 따라 서비스 안정성과 운영 비용이 크게 달라집니다.

데이터베이스 고가용성

메인프레임(Mainframe)과 유닉스(Unix)로 고성능 대용량 서버를 몇 대 구성하여 모든 트랜잭션을 처리하는 모놀리식 아키텍처(Monolithic Architecture)가 유행했던 시절이 있었습니다. DB의 고가용성을 보장하기 위해서는 장애 발생 시 처리하던 데이터를 다른 장비에서 재빨리 이어받아 처리할 수 있어야 했기에 스토리지와 파일시스템의 도움을 받아 장비 간에 데이터를 공유하게 하였습니다.

이와 같은 DB 고가용성은 클라우드나 MSA 환경에서도 당연히 보장되어야 합니다. 클라우드 환경에서는 AWS RDS(Relational Database Service)와 같은 매니지드 서비스를 사용할 수 있고 오픈소스 SW를 활용해 자체 구축할 수도 있습니다. 페이스메이커(Pacemaker)와 DRBD(Distributed Replicated Storage System)를 조합하여 고가용 스토리지 클러스터를 구성하거나 MHA(Master High Availability)를 활용한 마스터-슬레이브(Master-Slave) 구조의 DB 간 고가용성 솔루션도 있습니다. 아래 [그림 1]은 인프라 환경에 따른 이중화 구성 방안 예시입니다.

On-Premise향 아키텍처
  • Read 부하 분산: Single-Master Multiple-Slave 구성
  • Master 가용성 보장: OS clustering + Shared storage
  • OS Clustering
  • Master (Active)
  • Shared Storage
  • Master (Standby)
  • Master-slave Replication
  • Slave #1
  • Slave #2
  • Slave #3
Public cloud향 아키텍처
  • Cloud에서 제공하는 managed service 활용 (AWS RDS 등)
  • 고비용 managed service 대안으로 MHA를 활용한 HA 구성
  • Master: Node Manager
  • HA Manager
  • Master-slave Replication
  • Slave #1: Node Manager
  • Slave #2: Node Manager
[그림 1] 운영 환경에 따른 DB 이중화 구성 방안

2PC(Two-Phase Commit)

서로 다른 DB 간에 완벽한 정합성을 보장하는 방법입니다. 어느 순간에도 양쪽의 DB를 조회했을 때 합이 맞게 됩니다. 프로토콜의 기본 원리는 [그림 2]의 Phase #1과 같이 모든 DB에 반영할 수 있는지 물어봐서 합의가 되었을 때만 반영하고 그렇지 않으면 전체를 철회하는 방식입니다. 이를 통해서 부분적으로 적용되는 일을 막을 수 있습니다. MSA 특성상 개별 서비스의 패치 작업이 빈번하고 소규모 장애가 더 자주 발생할 가능성이 높습니다. 따라서 MSA 환경에서 2PC를 적용할 경우 전체 트랜잭션이 취소되어 오히려 단점으로 작용할 수 있으니 신중히 결정해야 합니다.

Phase #1
  • WAS: Prepare(준비됐니)?
  • DB X: Ok
  • WAS: Prepare(준비됐니)?
  • DB Y: Ok
  • 하나라도 OK가 오지 않으면 전체 Rollback
  • 모두 OK이면 합의 상태
Phase #2
  • WAS: Commit
  • DB X: Ok
  • WAS: Commit
  • DB Y: Ok
  • Phase #2에서는 반드시 Commit되어야 함
  • 각 DB별로 OK 응답이 올 때까지 재시도
[그림 2] 2PC 프로토콜

[그림 2]의 Phase #2를 보면 각 DB에 커밋(Commit)이 수행되므로 어느 한 쪽이 먼저 커밋될 수 있습니다. 이 시점에 양쪽을 조회하더라도 커밋되지 않은 쪽은 락(Lock)이 잡혀 있어서 불일치된 상태로는 절대 조회되지 않습니다. 락을 기반으로 정합성은 보장되지만 락이 풀리지 않으면 전역 장애를 유발할 수 있으므로 세밀한 주의가 필요합니다.

'Two-Phase'의 의미는 두 단계의 추가 통신(Prepare & Commit)을 한다는 것입니다. SQL이 수행되면 락을 잡기 시작하고 각 DB별로 두 번의 추가 통신을 한 다음 락이 풀리면서 비로소 반영됩니다. DB별로 최소 세 번의 통신이 이루어져야 하고 락 구간도 길기 때문에 성능이 떨어지는 단점이 있습니다.

신용카드 회사에서 시스템을 포인트서비스, 결제서비스로 구성한 상황을 상정해보겠습니다. 포인트를 활용하여 결제 대금을 지불하는 서비스를 구성할 때 포인트는 금전에 준하는 것이라 일시적 불일치도 허용하지 않겠다고 하면 2PC로 보장해줘야 합니다. 다만 위에 언급한 단점들을 감수할 수 있는 경우에만 활용해야 할 것입니다.

CDC(Change Data Capture)

지금부터 설명하는 방법은 최종 일관성(Eventual Consistency)을 보장하는 방식입니다. 일시적으로 양쪽의 합이 맞지 않을 수 있으나 궁극적으로 맞도록 하는 비동기 방식입니다. 2PC의 성능이 도저히 감당이 되지 않을 때 전역 장애를 방지하기 위해 비동기 방식을 적용합니다. CDC 솔루션은 [그림 3]과 같이 Source·Target DB 간에 비동기 복제 역할을 수행합니다. 제품군을 CDC라고 통칭하는데 핵심 기술이 Source DB에서 데이터를 추출하는 것이기 때문입니다. DB는 트랜잭션 변경 사항을 로그 파일로 남기는데 종류에 따라서 Oracle은 Redolog, MySQL·MariaDB는 Binlog, PostgreSQL은 WAL로 불립니다. 해당 파일에서 변경된 트랜잭션을 뽑아내고 Target DB로는 Insert·Update·Delete SQL문을 수행하여 반영합니다.

    데이터 변경, Source DB, 변경 로그 (Redo/archive log, Binlog, WAL), 실시간 추출, Extractor, 실시간 변경 내역 전달, Replicator, Target 복제, JDBC (INSERT, UPDATE, DELETE), Target DB [그림 3] 복제 흐름도

CDC는 2PC와 정반대로 Target DB에 장애가 발생하더라도 복구될 때까지 반복 수행하면서 기필코 반영시킵니다. 2PC의 Phase #2만 수행한다고 보면 됩니다. Source DB는 이미 반영이 완료된 것으로 취소할 수 없기 때문에 Target DB에 반드시 반영시켜야만 하고 트랜잭션이 끊겨 있으므로 비동기 처리하는 것은 당연합니다. 2PC와 반대의 방식이므로 빈번한 작업이 일어나는 MSA 환경에서 일시적인 오류를 잘 넘길 수 있습니다.

ETL(Extract, Transform, Load)과 CDC가 종종 비교됩니다. ETL은 주기적으로 SQL 쿼리를 수행하는 방식으로 활용이 가능하지만 서비스 단위로 실시간 동기화되는 CDC 방식이 더 적합합니다. 메일·캘린더·미팅·문서 서비스를 제공하는 그룹웨어 시스템을 예로 들어 보겠습니다. 그룹웨어의 각 서비스에 계정 서비스가 기반 역할을 해줘야 합니다. 계정을 처음 생성하면 자동으로 기본 메일함, 캘린더, 문서를 만들어 넣어줘야 합니다. 이때 일시적으로 메일서비스 패치 작업을 하고 있었더라도 계정 생성에 영향을 주지 않아야 하니 [그림 4]처럼 CDC로 자동화하는 것이 좋은 방법입니다. 실제 그룹웨어 시스템은 서비스 종류가 수십 개 이상이므로 이어서 설명할 SAGA 패턴으로 일일이 연계하고 보상 거래를 등록하기 어렵기 때문에 계정 초기화와 같이 반드시 성공해야 하는 경우라면 CDC가 유용합니다.

    계정 DB, CDC를 통한 실행 완료 보장, 메일 DB, 캘린더 DB, 미팅 DB, 문서 DB     [그림 4] 그룹웨어 계정 생성 및 초기화 흐름

SAGA 패턴

앞에서 언급한 방법들은 모두 시스템 소프트웨어가 보상 처리를 담당하는 방식이었는데, SAGA 패턴은 애플리케이션 개발자가 보상 트랜잭션을 잘 정의하고 누락되지 않도록 구성할 책임을 져야 합니다. 구체적인 예를 다루기 전에 클라이언트와 서버 간의 통신에서 발생하는 근본적인 문제에 대해 짚어 보겠습니다. 극단적인 사례로 생각될 수도 있겠지만 간과할 경우 찾아내기 어려운 데이터 불일치를 경험할 수 있기에 언급하고자 합니다. [그림 5]와 같이 클라이언트의 요청을 서버가 받아 데이터베이스에 반영하는 것까지는 성공했으나 그 후 클라이언트로 응답을 보내는 과정이 실패할 수 있습니다. 이 경우 서버는 성공한 상태로 남게 되지만 클라이언트는 오류 응답을 받게 되어 불일치 상태가 됩니다. 발생하지 않을 것 같지만 수많은 트랜잭션을 수행하다 보면 이런 상황이 생길 가능성도 배제할 수 없습니다.

    Client: 요청, Server: DB 반영, DB, Server: 네트워크 단절 또는 Server 오류, Client: 에러 리턴     [그림 5] 클라이언트-서버 간의 불일치 시나리오

클라이언트는 통신 오류를 받게 되면 서버가 처리에 성공했는지 실패했는지 알 수가 없습니다. 보상 트랜잭션은 2PC처럼 즉시 취소를 하거나 CDC처럼 처리가 완료될 때까지 반복하는 방법을 써야 합니다. 만약 간헐적으로 데이터 불일치가 발생하는데 그 원인을 도저히 모르겠다면 위와 같은 상황은 아닌지 확인해 볼 필요가 있습니다.

2PC 설명 시 언급했던 카드 포인트로 결제 대금을 처리하는 경우를 예로 들어 설명해보겠습니다. [그림 6]과 같이 DB 상태는 단계적으로 변경되며 일시적으로 정합성이 맞지 않는 시점이 존재합니다.

초기 상태
  • 포인트서비스: 포인트 100
  • 결제서비스: 결제금 1000
1단계: 포인트 출금
  • 포인트서비스: 100포인트 출금, 포인트 0
  • 결제서비스: 결제금 1000
2단계: 결제서비스 호출
  • 포인트서비스: 포인트 0
  • 100 결제 요청
  • 결제서비스: 결제금 1000
3단계: 결제대금 감액 완료
  • 포인트서비스: 포인트 0
  • 결제서비스: 100 감액, 결제금 900
[그림 6] 카드 포인트 전환 흐름도

포인트 출금까지는 성공한 상태에서 그 이후 단계에서 실패하면 포인트를 다시 복원해주거나 결제 대금을 제할 때까지 반복 수행을 해야 합니다. 2단계 과정에서 포인트서비스가 통신 오류 응답을 받았을 때 어떻게 처리하느냐가 중요합니다. 다음과 같이 두 가지 방법을 고려할 수 있습니다.

첫 번째, 포인트를 복원할 경우 [그림 7]과 같이 처리되어서 결제 대금은 차감되었으나 포인트는 여전히 남아 있어 회사에 손해를 입힐 수 있습니다. 이를 정상적으로 처리하기 위해서는 통신 오류 발생 시 결제서비스를 재호출하여 정상 응답이 올 때까지 반복수행해야 합니다. 결제서비스가 성공하였는데도 재시도될 경우 중복 감액이 되므로 결제서비스에서는 트랜잭션 ID를 기반으로 중복을 방지해야 합니다. 포인트서비스와 DB 구간에도 마찬가지 이슈가 있으므로 포인트서비스 역시 재시도 및 중복 방지를 해줘야 합니다. 해당 방식은 2PC를 적용한 것과 결과적으로 동일합니다.

초기 상태
  • 포인트서비스: 포인트 100
  • 결제서비스: 결제금 1000
1단계: 포인트 출금
  • 포인트서비스: 100포인트 출금, 포인트 0
  • 결제서비스: 결제금 1000
2단계: 결제서비스 호출
  • 포인트서비스: 포인트 0
  • 100 결제 요청
  • 결제서비스: 결제금 1000
3단계: 결제대금 감액 완료
  • 포인트서비스: 100포인트 복원, 포인트 100
  • 통신 오류
  • 결제서비스: 100 감액, 결제금 900
[그림 7] 단순한 오류 처리로 인한 부정합 사례

두 번째, 포인트를 복원하지 않고 결제 대금이 감소할 때까지 재시도하는 방법이 있습니다. 이 경우는 결제서비스만 국한해서 재시도와 중복 처리를 해주면 됩니다. 첫 번째 방식에 비해서 단순하며 CDC를 적용한 경우와 결과적으로 동일합니다.

두 가지 방식 중 어떤 것을 선택할지는 의사결정 사항인데 일반적으로 고객 입장에서는 포인트보다 결제 대금이 적은 것을 선호한다는 전제로 고객 친화적인 서비스를 제공한다면 구현하기가 수월한 두 번째 방식을 택하는 것이 낫습니다.

SAGA 패턴은 코레오그래피(Choreography)와 오케스트레이션(Orchestration) 방식으로 구현할 수 있습니다. 코레오그래피는 분산 구조로 서비스 간에 비동기 연계를 통한 이벤트 방식이고 오케스트레이션은 전체 트랜잭션을 관장하는 코디네이터(Coordinator)를 두고 이를 통해 보상 거래를 처리하는 방식입니다. 스프링 부트(Spring Boot)와 카프카(Kafka)를 활용하여 각각의 방식을 구현할 수 있습니다.

SAGA 패턴은 애플리케이션 레벨에서 수행하고 2PC·CDC는 시스템 소프트웨어가 담당하느냐의 차이가 있을 뿐 궁극적인 실행 결과는 동일합니다. SAGA 패턴은 표현력이 더 넓어서 보상 트랜잭션 구성 방식에 따라 2PC와 CDC의 효과를 모두 낼 수 있습니다. 다만 모든 보상 트랜잭션을 완벽하게 구성하는 것이 현실적으로 어려울 수 있으며 단계별 에러 케이스를 다 검증해야 하는 부담이 있습니다. 강한 정합성(Strong Consistency)은 2PC만 보장할 수 있습니다. 반드시 반영되어야 하는 케이스인데 SAGA 패턴으로 보상 거래를 기술하기 복잡하다면 CDC가 구성이 단순하고 안정적이므로 더 적합하다고 할 수 있습니다.

마치며

지금까지 분산 시스템 간의 데이터 동기화 방법에 대해 기본 원리와 간단한 사례를 들어 살펴보았습니다. SAGA 패턴이 MSA 사상에 가장 부합하는 방식이기는 하나 맹목적으로 따라서는 안 됩니다. 서비스와 시스템이 추구하는 가장 중요한 목표는 무엇이고 이에 부합하는 최적의 방법이 어떤 것인지를 면밀하게 검토한 후 결정해야 합니다. 장단점을 충분히 이해한 상태에서 기술적으로 감당할 수 있는 방안을 골랐다면 틀에 얽매일 필요는 없습니다. 잘 발생하지 않을 것 같은 케이스도 고려해야 나중에 이를 해결하기 위한 운영 비용을 절감할 수 있으니 이 점도 꼭 염두에 두어야 합니다. 앞서 서술한 내용은 필자의 실제 경험을 단순화하여 정리한 것으로 이 글을 읽는 개발자 및 시스템 운영관리자가 유사한 상황에 놓였을 때 도움이 되기를 바라겠습니다.

본문에서 다루지 않았지만 클라우드와 MSA는 리눅스 OS부터 풀스택(Full Stack)을 오픈소스 소프트웨어로 전환하는 것을 전제로 하고 있습니다. 전통적인 상용 소프트웨어(Proprietary Software)의 시대는 저물고 있지만 그렇다고 주위 평판만 믿고 오픈소스를 도입했다가는 낭패를 보기 십상입니다. 특히, 미션 크리티컬한 엔터프라이즈 시스템에 오픈소스를 적용할 때에는 사전에 전문가의 조언을 구해야 합니다.

오픈소스를 잘 다루면 IT 역량이 무궁무진해집니다. 에스코어는 글로벌 시장에서 검증받은 주요 오픈소스 소프트웨어에 대한 기술 커버리지를 확보하고 필요 시 소스코드 레벨까지 파고들어 분석합니다. CDC와 같이 운영환경에 쓸 만큼 성숙한 오픈소스가 없는 경우에는 자체 개발하여 적용하기도 합니다. 이러한 오픈소스 전문성을 바탕으로 기업들이 엔터프라이즈 플랫폼을 견고하게 구축·운영할 수 있도록 지원하고 있습니다.

# References
[1] DB 이중화 구성방안, MariaDB Korea Conference 발표
[2] Pacemaker
[3] DRBD(Distributed Replicated Storage System)
[4] MHA(Master High Availability)
[5] 2PC(Two-Phase Commit)
[6] Consistency Model
[7] Data Integration(CDC/ETL 등)
[8] SAGA Pattern
[9] Choreography Saga Pattern
[10] Orchestration Saga Pattern
[11] 서비스 경량화를 위한 MSA 설계 시 고려사항



▶  해당 콘텐츠는 저작권법에 의하여 보호받는 저작물로 기고자에게 저작권이 있습니다.
▶  해당 콘텐츠는 사전 동의 없이 2차 가공 및 영리적인 이용을 금하고 있습니다.


이 글이 좋으셨다면 구독&좋아요

여러분의 “구독”과 “좋아요”는
저자에게 큰 힘이 됩니다.

subscribe

구독하기

subscribe

서성한
서성한 IT 테크놀로지 전문가

에스코어(주) 소프트웨어사업부 컨버전스SW그룹

시스템 SW 및 오픈소스 SW 전문 아키텍트로서 미들웨어, OS kernel, 메일엔진 등을 개발하였습니다. 현재는 오픈소스 SW와 엔터프라이즈 플랫폼을 담당하고 있습니다.

공유하기