요약
- 12장. 데이터 시스템의 미래에 대해 이해함.
- 데이터 통합
- 파생 데이터에 특화된 도구의 결합
- 데이터플로에 대한 추론
- 파생 데이터 대 분산 트랜잭션
- 전체 순서화의 제약
- 인과성 획득을 위한 이벤트 순서화
- 일괄 처리와 스트림 처리
- 파생 상태 유지
- 애플리케이션 발전을 위한 데이터 재처리
- 람다 아키텍처
- 일괄 처리와 스트림 처리의 통합
메모
12장. 데이터 시스템의 미래
- 마지막 장에서는 미래의 관점으로 바꾸어 애플리케이션 설계와 구축 방법의 근본적 개선을 위한 아이디어와 접근법을 제시함.
- 미래에 대한 의견은 주관적이기에, 이 장에서는 저자의 개인적인 의견을 일인칭으로 표현함.
- 이 장의 목표는 생산적인 토론의 출발점이 되고, 혼란스러운 개념을 명확히 하는 데 도움을 주는 것임.
- 책의 목적은 신뢰할 수 있고, 확장 가능하며, 유지보수하기 쉬운 애플리케이션과 시스템을 만드는 방법을 탐구하는 것임.
- 이를 위해 신뢰성 개선을 위한 내결함성 알고리즘, 확장성 개선을 위한 파티셔닝, 유지보수성 개선을 위한 진화와 추상화 메커니즘 등 다양한 주제를 다루었음.
- 이번 장에서는 이러한 아이디어들을 결합해 미래를 고찰하며, 더 나은 애플리케이션을 설계하는 방법을 발견하는 것을 목표로 함.
데이터 통합
- 이 책에서는 여러 문제에 대한 해결책들의 장점과 단점, 그리고 트레이드오프를 설명하는 것이 되풀이되는 주제임.
- 예를 들어 저장소 엔진과 복제 접근법 등에 대해 다루었음.
- 모든 문제에 대한 완벽한 해결책은 없지만, 상황에 따라 적절한 서로 다른 접근법이 존재함.
- 일반적으로 소프트웨어 구현 시 특정 접근법 하나를 채택하며, 하나의 코드 경로로 견고하게 만들기는 어려움.
- 따라서 가장 적절한 소프트웨어 도구 선택이 상황에 따라 다름.
- 범용 데이터베이스라 불리는 일부 소프트웨어도 특정 사용 양식에 맞춰 설계됨.
- 선택의 폭이 넓을 경우, 첫 번째 난제는 소프트웨어 제품과 그 제품이 잘 어울리는 환경 사이의 대응 관계를 파악하는 것임.
- 벤더는 자신들의 소프트웨어가 적합하지 않은 작업부하에 대해 말하기를 꺼림.
- 이전 장에서의 질문들을 활용해 트레이드오프를 이해하면 도움이 됨.
- 그러나 도구와 사용 환경 사이의 대응 관계를 완벽하게 이해하더라도, 복잡한 애플리케이션에서는 데이터를 여러 가지 다른 방법으로 사용함.
- 모든 상황에 적합한 소프트웨어가 존재할 가능성은 낮아, 원하는 애플리케이션 기능을 제공하기 위해 여러 다른 소프트웨어를 함께 사용해야 함.
파생 데이터에 특화된 도구의 결합
- 예를 들어, OLTP 데이터베이스와 전문 검색 색인을 통합하는 요구는 일반적임.
- 포스트그레스큐엘과 같은 데이터베이스는 간단한 애플리케이션에는 충분한 전문 색인 기능이 포함되어 있지만, 더 복잡한 검색 기능을 위해 전문적인 정보 탐색 도구가 필요함.
- 반대로, 검색 색인은 일반적으로 지속성 있는 레코드 시스템으로는 적합하지 않아, 많은 애플리케이션은 요구사항을 만족하기 위해 두 도구를 결합해 사용함.
- 데이터를 다루는 범위가 넓어지면, 데이터 시스템을 통합하기가 더 어려워짐.
- 데이터베이스와 검색 색인 외에도, 분석 시스템(데이터 웨어하우스나 일괄 처리 또는 스트림 처리 시스템)에 해당 데이터의 사본을 유지할 필요가 있음.
- 캐시나 원본 데이터에서 파생된 객체의 비정규화 버전을 유지하거나, 머신러닝, 분류, 랭킹, 추천 시스템으로 데이터를 전달하며 데이터 변화를 기반으로 알림을 보내기도 함.
- 소프트웨어 엔지니어들이 종종 "내가 해봤는데 사람들 99%는 X만 있으면 돼" 또는 "사람들 99%는 X가 전혀 필요없어"라고 말하는 것은, 기술의 실제 유용성보다는 화자의 경험을 반영함.
- 데이터 통합의 필요성은 조직 전체 데이터플로를 고려할 때야 명확해짐.
- 어떤 사람에게는 의미 없는 기능이 다른 사람에게는 핵심 요구사항일 수 있음.
데이터플로에 대한 추론
- 데이터 접근 양식을 만족하기 위해 같은 데이터의 사본을 여러 저장소 시스템에 유지할 때, 입력과 출력을 명확히 구분할 필요가 있음.
- 데이터의 처음 기록 위치, 어떤 표현형이 어떤 원본에서 파생되는지, 데이터를 올바른 장소와 형식으로 어떻게 넣는지에 대해 충분히 고려해야 함.
- 예를 들어, 데이터를 먼저 레코드 데이터베이스 시스템에 기록한 후, 변경 데이터 캡처(CDC)를 사용해 검색 색인에 변경 사항을 동일한 순서로 반영한다고 가정하면, 일관성이 보장됨.
- 이 시스템에서 새로운 입력을 공급하는 유일한 방법은 데이터베이스 쓰기임.
- 그러나 애플리케이션이 검색 색인과 데이터베이스에 직접 데이터를 기록하게끔 하면, 두 저장소 시스템에서 데이터를 처리하는 서로 다른 순서로 인해 충돌이 발생하고, 영구적인 불일치가 발생할 수 있음.
- 쓰기의 순서를 결정하는 단일 시스템으로 모든 사용자 입력을 처리하면, 데이터를 다른 표현형으로 파생하기가 쉬워짐.
- 이 접근법은 상태 기계 복제 접근법의 응용임.
- 변경 데이터 캡처를 사용하든 이벤트 소싱 로그를 사용하든 전체 순서를 결정하는 것이 더 중요함.
- 파생 데이터 시스템이 이벤트 로그를 기반으로 갱신하면, 결정적이고 멱등성을 가지며 결함에서 복구하기가 쉬워짐.
파생 데이터 대 분산 트랜잭션
- 파생 데이터와 분산 트랜잭션은 서로 다른 데이터 시스템 간 일관성을 유지하는 다른 방식으로 유사한 목표를 달성함.
- 분산 트랜잭션은 상호 배타적인 잠금을 사용해 쓰기 순서를 결정하고, 원자적 커밋을 사용해 변경 효과가 정확히 한 번 나타나도록 보장함.
- 반면, CDC와 이벤트 소싱은 로그를 사용해 순서를 결정하고, 결정적 재시도와 멱등성을 기반으로 함.
- 분산 트랜잭션 시스템은 일반적으로 선형성을 지원하며, 자신이 쓴 내용 읽기와 같은 유용한 기능을 보장함.
- 하지만, 파생 데이터 시스템은 대개 비동기로 갱신되어 기본적으로 동시간 갱신 보장을 하지 않음.
- 분산 트랜잭션 비용을 감내할 만한 제한된 환경에서 성공적으로 사용되어 왔지만, XA는 결함 대응에 취약하고 성능 면에서도 좋지 않음.
- 따라서 XA의 유용성은 매우 제한적임.
- 분산 트랜잭션에 더 적합한 프로토콜이 필요하지만, 이는 기존 도구와 통합되는 것이 어렵고 근시일 내에는 이루어지지 않을 것임.
- 로그 기반 파생 데이터는 이종 데이터 시스템을 통합하는 가장 장래성 있는 접근법으로 보이지만, 자신이 쓴 내용 읽기를 보장하는 것은 여전히 유용함.
- 최종적 일관성을 어떻게 다루는지에 관한 훌륭한 지침이 없으면, 모든 사람들에게 "최종적 일관성이 필수야 받아들이고 배워"라고 말하는 것은 생산적이지 않음.
- 더 강력한 보장을 구현하는 몇 가지 방법이 있으며, 분산 트랜잭션과 비동기 로그 기반 시스템 사이 중간 지점을 찾아볼 수 있음.
전체 순서화의 제약
- 전체 순서화의 제약이 작은 시스템에서는 이벤트 로그의 전체 순서를 보장할 수 있지만, 규모가 커지고 복잡한 작업부하가 발생함에 따라 한계가 드러남. 이러한 한계는 다음과 같음
- 전체 순서가 정해진 로그를 구축하려면, 모든 이벤트가 단일 리더 노드를 통해야 함.
- 처리량이 단일 장비에서 처리할 수 있는 양보다 커지면 복수의 장비로 파티셔닝을 해야 하며, 그 결과 다른 두 파티션의 이벤트 순서는 애매해짐.
- 서버가 지역적으로 분산된 여러 데이터센터에 걸쳐있을 경우, 일반적으로 각 데이터센터에 독립적인 리더를 둠.
- 이는 네트워크 지연 때문에 데이터센터를 걸쳐 동기식으로 코디네이션하는 것이 비효율적이기 때문임.
- 즉, 두 가지 다른 데이터센터에서 나온 이벤트는 서로 순서가 정해지지 않았다는 의미임.
- 애플리케이션을 마이크로서비스로 배포할 때, 각 서비스와 서비스의 지속적인 관련 상태 정보를 독립된 단위로 배포하고 지속적인 상태는 서비스 간에 공유하지 않는 것이 일반적임.
- 두 이벤트가 서로 다른 서비스에서 발생했다면 이들 사이에는 정해진 순서가 없음.
- 어떤 애플리케이션은 클라이언트 측 상태를 유지하고 사용자 입력이 들어올 때마다 서버의 확인 응답을 기다리지 않고 바로 갱신함.
- 이런 애플리케이션은 이벤트의 순서가 클라이언트와 서버에서 서로 다를 가능성이 높음.
- 전체 순서 브로드캐스트는 이벤트의 전체 순서를 결정하는 것을 말하며, 합의와 동등함.
- 대부분의 합의 알고리즘은 단일 노드가 전체 이벤트 스트림을 처리하기에 충분한 처리량을 가진 상황을 가정하고 설계함.
- 이 알고리즘들은 이벤트 순서를 정하는 작업을 여러 노드에서 공유하는 메커니즘은 제공하지 않음.
- 단일 노드의 처리량을 넘어서는 규모와 지리적으로 분산된 설정에서 잘 동작하는 합의 알고리즘 설계는 아직 해결되지 않은 연구 과제임.
- 즉, 전체 순서화의 제약으로 인해 크고 분산된 시스템에서 이벤트 로그의 전체 순서를 보장하기 어려움.
- 이러한 한계를 극복하기 위한 합의 알고리즘을 찾고 개발하는 것이 현재 연구 분야의 중요한 과제로 남아있음.
인과성 획득을 위한 이벤트 순서화
- 인과성 획득을 위한 이벤트 순서화에서는 이벤트 간 인과성이 없는 경우 전체 순서가 정해지지 않아도 큰 문제가 아님.
- 동시에 발생한 이벤트는 임의로 순서를 정할 수 있기 때문임.
- 하지만 때로는 인과성이 미묘한 방식으로 발생하기도 함.
- 문제 해결을 위한 출발점 몇 가지를 보자.
- 논리적 타임스탬프를 사용하면 전체 순서화를 지원할 수 있지만, 여전히 수신자가 잘못된 순서로 전달된 이벤트를 처리해야 하고 추가로 메타데이터를 전달해야 함.
- 사용자가 결정을 내리기 전에 사용자가 본 시스템 상태를 기록하는 이벤트를 로깅할 수 있고 해당 이벤트에 고유 식별자를 부여할 수 있다면, 이후 이벤트는 인과적 의존성을 기록하기 위한 이벤트 식별자를 참조할 수 있음.
- 충돌 해소 알고리즘은 예상치 못한 순서로 전송된 이벤트를 처리하는 데 도움을 줌.
- 이 알고리즘은 상태를 유지하는 데 유용하지만, 외부 부수효과가 있다면 도움이 되지 않음.
- 아마도 시간이 흐르면 모든 이벤트가 전체 순서 브로드캐스트의 병목을 거치지 않고서도 인과적 의존성을 효율적으로 캡처하고 파생 상태를 정확히 유지하는 애플리케이션 개발 패턴이 등장할 것임.
일괄 처리와 스트림 처리
- 일괄 처리와 스트림 처리는 데이터 통합의 목표인 데이터를 올바른 장소에 올바른 형태로 두기 위한 도구임.
- 이들의 출력은 파생 데이터셋이며, 검색 색인, 구체화 뷰, 사용자에게 보여주기 위한 추천, 집계 지표 등이 포함됨.
- 일괄 처리와 스트림 처리는 여러 공통 원리가 있지만, 근본적인 주요 차이점은 스트림 처리는 끝이 없는 데이터셋 상에서 운영되는 반면 일괄 처리는 유한한 크기의 입력을 사용한다는 것임.
- 처리 엔진을 구현하는 방법에도 세부적으로 많은 차이가 있지만 이런 구분은 희미해지기 시작했음.
- 예를 들어, 스파크는 일괄 처리 엔진 상에서 스트림을 처리하며, 스트림을 마이크로 일괄 처리 단위로 나누어 일괄 처리함.
- 반면 아파치 플링크는 스트림 처리 엔진 상에서 일괄 처리를 수행함.
- 이론적으로는 한 가지 처리 유형을 다른 유형 위에서 애뮬레이션할 수 있지만, 성능 특성은 다양하게 나타남.
- 마이크로 일괄 처리는 홉핑 윈도우나 슬라이딩 윈도우를 구현하기에는 성능이 좋지 않음.
파생 상태 유지
- 일괄 처리와 스트림 처리는 결정적이고 출력이 입력에만 의존하는 순수함수를 장려하며, 이 원리는 내결함성에 도움이 되고 데이터플로 추론을 단순화함.
- 파생 데이터 시스템은 관계형 데이터베이스의 트랜잭션 내에서 보조 색인을 동기식으로 갱신하는 것처럼 동기식으로 운영할 수 있으나, 비동기 방식을 사용하면 이벤트 로그 기반 시스템을 훨씬 견고하게 만듦.
- 비동기 방식은 시스템 일부의 결함이 국소적으로 남아 있게 해준다.
- 반면, 분산 트랜잭션은 참여 장비 일부가 실패하면 어보트하기 때문에 나머지 시스템으로 실패가 확산되어 실패가 증폭되는 경향이 있음.
- 보조 색인을 가진 파티셔닝된 시스템에서는 색인을 비동기 방식으로 유지하면 파티션 간 통신에서 신뢰성과 확장성이 좋아짐.
애플리케이션 발전을 위한 데이터 재처리
- 파생 데이터를 유지할 때 일괄 처리와 스트림 처리는 모두 유용하며, 이를 통해 기존 데이터를 재처리하여 새로운 요구사항에 대응할 수 있음.
- 재처리를 이용하면 데이터셋을 완전히 다른 모델로 재구축할 수 있음.
- 파생 뷰를 사용하면 점진적 발전이 가능함.
- 이전 스키마와 새 스키마를 함께 유지하여 독립적인 파생 뷰를 만들고, 점진적으로 새 뷰를 접근하는 사용자의 비율을 늘려 나갈 수 있음.
- 점진적 이전의 장점은 처리의 모든 단계에서 뭔가 잘못됐을 때 쉽게 이전으로 되돌릴 수 있다는 점임.
- 언제든지 돌아갈 수 있는 동작하는 시스템이 남아 있어, 새로 하는 작업에 자신감을 가질 수 있고 시스템을 빠르게 개선해 갈 수 있음.
람다 아키텍처
- 람다 아키텍처는 일괄 처리와 스트림 처리를 결합한 아이디어로, 입력 데이터를 불변 이벤트로 기록하고, 읽기에 최적화된 뷰를 파생한다. 이 아키텍처에서는 일괄 처리 시스템과 스트림 처리 시스템을 병행해서 운용한다. 스트림 처리자는 근사 갱신을 반영하고, 일괄 처리자는 정확한 버전의 파생 뷰에 반영한다.
- 람다 아키텍처는 데이터 시스템 설계에 영향을 미쳤지만, 몇 가지 실질적 문제가 있음.
- 일괄 처리와 스트림 처리 양쪽 프레임워크에서 같은 로직을 유지해야 하며, 디버깅과 튜닝, 운영상 복잡성이 존재함.
- 스트림 파이프라인과 일괄 처리 파이프라인은 분리된 출력을 생산하므로, 사용자 요청에 대응하기 위해 출력을 병합해야 함.
- 전체 과거 데이터를 재처리할 수 있지만, 대용량 데이터셋에서 자주 수행하면 비용이 만만치 않음.
- 증분으로 일괄 처리하면 복잡성이 증가하고, 일괄 처리 레이어의 목표와 배치됨.
일괄 처리와 스트림 처리의 통합
- 최근에는 일괄 처리와 스트림 처리의 통합을 통해 람다 아키텍처의 단점을 해결하려는 노력이 진행되고 있음.
- 이를 위한 필요한 기능들은 다음과 같음.
- 최근 이벤트 스트림을 다루는 처리 엔진에서 과거 이벤트를 재생하는 능력. 로그 기반 메시지 브로커나 스트림 처리자에서 이 기능을 제공함.
- 스트림 처리자에서 사용되는 정확히 한 번 시맨틱. 이 기능은 결함이 발생하더라도 결함이 없었던 상황과 동일한 출력을 보장함.
- 이벤트 시간 기준으로 윈도우를 처리하는 도구. 처리 시간 기준은 과거 이벤트 처리에서 의미가 없음.
- 예로 아파치 빔(Apache Beam)이 이러한 연산을 표현하는 API를 제공함.
- 이러한 기능들은 이미 사용 가능한 범위가 확장되어 일괄 처리와 스트림 처리를 통합하는 시스템을 구축할 수 있음.
댓글