3.4

View in English

3.4 데이터 아키텍처와 저장소

개요와 동기

데이터는 코드보다 오래 삽니다. 애플리케이션은 몇 년마다 다시 쓰이지만, 그것이 관리하는 데이터(고객 기록, 재무 원장, 급여 이력, 건강 기록)는 수십 년 지속됩니다. 흔히 조직에서 가장 가치 있고 가장 규제받는 자산입니다. 데이터 아키텍처는 그 데이터를 어떻게 모델링하고, 어디에 저장하고, 어떻게 일관되게 유지하고, 어떻게 진화시키고, 규모에서 충분히 빠르게 제공할지 결정하는 규율입니다. 대규모 조직에서 이 결정들은 근본적입니다. 저장 엔진과 데이터 모델의 선택은 시스템의 전 수명 동안 비즈니스가 무엇을 할 수 있는지, 얼마나 빨리 움직일 수 있는지, 비용이 얼마나 드는지를 제약합니다.

규모, 수명, 규제 때문에 기업과 정부에서 이해관계가 가장 높습니다. 은행의 거래 저장소는 한 푼도 잃거나 이중으로 세어서는 안 됩니다. 정부 등록부는 법정 기간 동안 기록을 보존하고 감사자에게 무결성을 입증해야 합니다. 건강 시스템은 세밀한 접근 및 거주 규칙을 시행해야 합니다. 동시에 이 조직들은 엄청난 읽기와 쓰기 양을 처리하며 모든 질의가 단일 관계형 데이터베이스에 닿는 것을 감당할 수 없습니다. 그래서 데이터 아키텍처는 정확성과 내구성을 성능과 규모와 조화시켜야 하며, 새 의무를 충족하느라 스키마가 계속 변하는 동안 그렇게 해야 합니다.

이 장은 주요 저장 패러다임과 각각을 쓸 때, 폴리글랏 영속성의 규율, 데이터 모델링과 흔히 과소평가되는 스키마 진화 및 이전의 문제, 캐싱과 CDN(콘텐츠 전송 네트워크)과 악명 높게 어려운 무효화 문제, 트랜잭션, 락, 동시성이 규모로 밀어붙일 때 어떻게 동작하는지를 다룹니다. 관통하는 줄기는 단순합니다. 보편적인 데이터베이스는 없습니다. 트레이드오프가 있고, 좋은 데이터 아키텍처란 워크로드 하나하나마다 그것을 의식적으로 고르는 것입니다.

핵심 원칙

  • 데이터를 접근 패턴에 맞게 모델링하고, 그 반대가 아닙니다. 추상적인 “올바른” 모델이 아니라 데이터가 어떻게 읽히고 쓰일지를 중심으로 저장소를 설계하십시오.
  • 모든 것을 지배하는 하나의 데이터베이스는 없습니다. 워크로드마다 다른 엔진을 원하며, 규모에서 폴리글랏 영속성은 정상입니다.
  • 기록 시스템에는 정확성이 먼저입니다. 권위 있는 데이터에 내구성과 일관성은 협상 불가이며, 성능은 그것을 관통하지 말고 그 주위에서 최적화하십시오.
  • 스키마는 바뀔 것이니 계획하십시오. 이전은 일회성이 아니라 일급의 지속적인 엔지니어링 활동입니다.
  • 서비스 경계 뒤에서 데이터를 소유하십시오. 각 바운디드 컨텍스트(자체의 명시적 경계를 가진 독립적인 도메인 모델)는 자기 데이터를 소유합니다. 데이터베이스를 공유하면 팀이 결합되고 자율성이 무너집니다.
  • 캐싱은 성능 이득으로 위장한 정확성 문제입니다. 모든 캐시는 오래됨과 무효화 위험을 도입하므로 의도적으로 다루십시오.
  • 비정규화는 죄가 아니라 거래입니다. 읽기 성능을 위한 데이터 중복은 일관성의 결과를 책임진다면 정당합니다.
  • 일관성과 규모는 맞바꿉니다. 트랜잭션 보장이 강할수록 분산하기 어려우니, 워크로드가 필요로 하는 것만 사십시오.

권장 사항

워크로드로부터 저장 패러다임을 고른다

각 워크로드를 맞는 모델에 맞추십시오. 관계형 데이터베이스는 강한 일관성, 조인, 성숙한 트랜잭션을 주며, 기록 시스템과 복잡한 무결성 규칙이 있는 모든 것의 기본입니다. 문서 저장소는 하나의 단위(주문 전체, 프로필 전체)로 읽히는 계층적이고 스키마가 유연한 데이터에 맞습니다. 키-값 저장소는 단순한 조회(세션, 기능 플래그, 캐시)에 극단적인 속도를 줍니다. 그래프 데이터베이스는 관계가 곧 질의인 곳(사기 조직, 조직도, 권한, 공급망)에서 뛰어납니다. 컬럼형 저장소는 수십억 행에 걸쳐 적은 컬럼을 스캔하는 분석 질의(데이터 웨어하우스, 보고)를 구동합니다. 시계열 데이터베이스는 추가가 많고 타임스탬프가 있는 데이터(지표, 텔레메트리, 사물 인터넷(IoT) 센서, 시장 데이터)에 최적화되어 있습니다. 하나의 엔진이 모든 일을 하도록 강요하지 마십시오. 관계형 데이터베이스를 큐로, 문서 저장소를 원장으로 쓰면 고통을 부릅니다.

폴리글랏 영속성을 의도적으로 채택한다

대규모 시스템은 정당하게 여러 저장소를 씁니다. 관계형 기록 시스템, 검색 색인, 캐시, 분석 웨어하우스, 어쩌면 그래프나 시계열 엔진입니다. 이것이 폴리글랏 영속성이며, 워크로드가 진정으로 다를 때 맞는 패턴입니다. 비용은 운영적입니다. 이제 운영하고, 보호하고, 백업하고, 인력을 대야 할 엔진이 더 많기 때문입니다. 각 저장소를 서비스가 소유하는 것으로 다루고, 운영 도구를 표준화하고, 기술의 수를 자리를 얻은 것으로만 유지해 그 비용을 관리하십시오. 사소한 필요마다 새 데이터베이스를 채택하는 것을 경계하십시오. 각각이 영구적인 운영상의 약속입니다.

데이터를 모델링하고 스키마 진화를 지속적인 것으로 다룬다

기록 시스템에는 선행 데이터 모델링에 투자하십시오. 무결성을 지키려 정규화하고, 증명된 읽기 핫스팟에는 선택적으로 비정규화하십시오. 모델이 무엇이든 스키마는 영원히 진화하므로, 이전을 안전하고 일상적으로 만드십시오. 소스 관리에 체크인되고 배포 파이프라인으로 적용되는 버전 관리되고 자동화된 전진 전용 이전 스크립트를 쓰십시오. 큰 테이블의 무중단 변경에는 확장-축소(병렬 변경) 패턴을 쓰십시오. 새 컬럼이나 테이블을 추가하고, 백필하며 이중 쓰기를 하고, 읽는 쪽을 이전하고, 그다음 옛 형태를 제거합니다. 단일한 호환 파괴적 alter는 안 됩니다. 옛 코드와 새 코드가 동시에 돌 수 있도록 스키마 변경을 배포에 걸쳐 하위 호환되게 만드십시오. 이벤트 소싱이나 메시지 기반 시스템에서는 이벤트와 메시지 스키마를 명시적으로 버전 관리하고 옛 이벤트의 업캐스팅(읽을 때 현재 스키마로 변환)을 지원하십시오.

캐싱과 무효화를 눈을 뜨고 설계한다

캐싱과 CDN은 지렛대 효과가 가장 큰 성능 도구입니다. CDN은 사용자 가까운 엣지에서 정적이고 캐시 가능한 콘텐츠를 제공하고, 애플리케이션 캐시는 반복되는 읽기에서 데이터베이스를 구합니다. 하지만 어려운 부분은 무효화, 곧 캐시된 데이터가 오래되었음을 아는 것입니다. 경우마다 전략을 고르십시오. 약간의 오래됨이 허용되고 가장 단순한 곳에서는 시간 기반 만료(TTL)를 쓰십시오. 신선도가 중요한 곳에서는 명시적 무효화나 write-through를 쓰십시오. 애플리케이션이 채움을 관리하는 곳에서는 cache-aside를 쓰십시오. TTL을 의식적으로 설정하고, 락이나 요청 병합으로 캐시 스탬피드(많은 클라이언트가 같은 만료된 항목을 한꺼번에 다시 만듦)를 막고, 콜드 캐시의 천둥 떼를 방지하십시오. 오래됨이 정확성이나 컴플라이언스 실패를 일으킬 수 있는 데이터(권한, 잔액, 동의)는 명시적이고 테스트된 무효화 경로 없이 절대 캐시하지 마십시오. 캐시 키, TTL, 무효화를 부수적 설정이 아니라 설계된 산출물로 다루십시오.

규모를 위해 트랜잭션, 락, 동시성을 관리한다

격리 수준을 이해하고 각 트랜잭션에 여전히 올바른 가장 약한 것을 고르십시오. 높은 격리는 동시성을 희생하기 때문입니다. 경합이 낮고 읽기가 많은 워크로드에는 낙관적 동시성(쓸 때 버전 검사)을 선호하고, 진짜 뜨거운 경합일 때만 비관적 락에 손을 뻗되 데드락을 피하도록 락을 짧고 일관된 순서로 유지하십시오. 확장하면 쓰기 가능한 단일 데이터베이스가 병목이 됩니다. 읽기 확장을 위해 읽기 복제본을 도입하고(복제 지연을 받아들임), 부하를 고르게 퍼뜨리면서 관련 데이터를 함께 두어 샤드 간 트랜잭션을 피하는 키로 샤딩/파티셔닝하십시오. 샤딩이 쉬운 샤드 간 조인과 다중 샤드 ACID(원자성, 일관성, 격리성, 지속성) 트랜잭션을 내준다는 것을 기억하십시오. 사가와 비정규화가 등장하는 이유가 흔히 이것입니다. 워크로드가 요구할 때만 이런 기법을 들이십시오. 성급한 샤딩은 영구적인 복잡성을 더합니다.

장단점

저장소 유형가장 알맞은 용도강점약점
관계형기록 시스템. 복잡한 무결성ACID. 조인. 성숙한 도구쓰기를 수평 확장하기 더 어려움
문서집합체 읽기. 유연한 스키마빠른 객체 전체 읽기/쓰기. 유연함약한 문서 간 조인/트랜잭션
키-값세션. 캐시. 단순 조회극단적 속도와 규모키 이상의 질의 없음
그래프관계 위주 질의빠른 순회. 표현력틈새 운영 기술. 확장 한계
컬럼형분석. 보고빠른 집계 스캔. 압축행 단위 트랜잭션 쓰기에 부적합
시계열지표. 텔레메트리. IoT효율적인 추가와 시간 질의좁은 목적

지배적인 트레이드오프는 일관성 및 풍부한 질의 대 수평 확장성 및 속도입니다. 관계형 시스템은 가장 강한 보장과 가장 유연한 질의를 주지만, 여러 기계에 걸친 쓰기 확장이 가장 어렵습니다. NoSQL(비관계형) 계열은 조인, 트랜잭션, 스키마를 완화해 규모와 속도를 얻습니다. 캐싱은 신선도를 지연과 맞바꿉니다. 샤딩은 파티션 간 트랜잭션을 쓰기 처리량과 맞바꿉니다. 어느 것도 보편적으로 옳지 않습니다. 기술은 각 워크로드를 정확성과 성능 요구가 실제로 요구하는 곡선 위의 점에 놓는 것입니다.

팀과 논의할 질문

  1. 핵심 데이터셋마다 모두가 하나의 기록 시스템을 말할 수 있습니까, 아니면 캐시와 투영이 조용히 진실로 다뤄집니까? 데이터는 코드보다 오래 살고, 가장 해로운 데이터 인시던트는 표류에서 옵니다. 캐시, 검색 색인, 읽기 투영이 권위 있는 것으로 오인되어 실제 원천에서 조용히 갈라집니다. 큰 팀에서는 소유권이 흐릿하고 여러 서비스가 겹치는 사본을 쓸 때 일어나며, 인시던트 중에 아무도 어느 값이 맞는지 말할 수 없습니다. 중요한 데이터의 지도를 가져와, 각 항목에 권위 있는 단일 저장소와 그것으로부터 재구축 가능해야 하는 파생 사본을 표시하십시오. 금융과 정부에서 어느 기록이 법적 원천인지 입증하고 나머지를 재구축할 수 있는 것은 흔히 편의가 아니라 규제 요건입니다. 기록 시스템에서 재구축할 수 없는 것은 의도했든 아니든 그 자체가 기록 시스템입니다.

  2. 자산 내 각 데이터베이스 엔진을 운영하고, 보호하고, 백업하는 데 실제로 비용이 얼마나 들며, 모두가 여전히 자리를 얻고 있습니까? 폴리글랏 영속성은 워크로드가 진정으로 다를 때 맞지만, 각 엔진은 영구적인 운영상의 약속입니다. 패치, 백업, 모니터링, 보안 리뷰, 새벽 3시에 그것을 아는 인력입니다. 대규모 조직은 기능 하나씩을 위해 채택한 저장소의 동물원으로 표류할 수 있고, 한계 엔진은 이미 운영하는 저장소가 처리할 수 있는 워크로드를 제공하며 영원히 비용을 더합니다. 모든 엔진, 그것을 정당화하는 워크로드, 누가 호출 대기인지 나열하고, 이제 주 저장소가 충족할 수 있는 필요로 채택된 것을 표시하십시오. 새 데이터베이스 채택은 높은 기준을 통과해야 합니다. 나중에 하나를 제거하는 것은 또 한 번의 이전을 뜻하기 때문입니다. 유지하는 저장소 전반에서 운영 도구를 표준화하는 것이 하나의 엔진이 모든 일을 하도록 강제하지 않고 비용을 낮게 유지하는 방법입니다.

  3. 사용자가 자신의 쓰기 직후 복제본에서 오래된 값을 읽을 수 있는 곳은 어디이며, 그것이 약속을 깹니까? 읽기 복제본은 읽기를 확장하지만 주 데이터베이스보다 지연되므로, 프로필을 갱신하고 즉시 다시 불러오는 사용자가 옛 값을 볼 수 있고, 이는 버그로, 잔액이나 동의 플래그의 경우 컴플라이언스 실패로 읽힙니다. 흐름마다 자신의 쓰기 읽기가 중요한지 결정하고, 그 읽기를 주 데이터베이스로 라우팅하거나 세션 일관성 메커니즘을 쓰십시오. 복제본이 제공하는 흐름의 목록을 가져와 사용자가 쓴 직후 곧바로 행동하는 것을 표시하십시오. 잔액, 권한, 동의에서는 오래된 읽기를 외관상의 문제가 아니라 정확성 실패로 다루십시오. 요점은 각 워크로드가 실제로 필요한 일관성을 사고, 받아들이는 오래됨을 우연이 아니라 명시적으로 하는 것입니다.

  4. 오늘 가장 크고 가장 바쁜 테이블의 스키마를 무중단으로 바꿀 수 있으며, 확장-축소 단계를 실제로 리허설한 사람이 누구입니까? 스키마는 영원히 진화하며, 가장 아픈 실패는 거대한 테이블을 잠그고, 서비스를 얼리고, 깔끔하게 롤백할 수 없는 빅뱅 alter입니다. 큰 팀에서 위험은 곱절이 됩니다. 여러 서비스가 같은 모양을 읽으므로 호환 파괴적 변경은 단계적 배포에 걸쳐 옛 코드와 새 코드가 나란히 돌아야 하기 때문입니다. 상충하는 끌림은 속도입니다. 단일 alter는 쓰기 빠르지만, 확장-축소(새 형태 추가, 백필, 이중 쓰기, 읽는 쪽 이전, 옛 형태 삭제)는 단계도 인내도 더 필요합니다. 가장 큰 테이블, 순진한 alter가 얼마나 오래 잠글지에 대한 정직한 추정, 이론이 아니라 리허설에서 누군가 끝까지 실행해 본 구체적 이전을 가져오십시오. 지속적으로 돌고 법정 가용성 목표를 지닌 기업과 정부 시스템에서 이전을 위한 다운타임은 위반이므로, 확장-축소 규율은 스키마를 바꿀 수 있도록 허락받는 값입니다.

  5. 캐시되거나 복제된 값 중 어느 것이 오래된 채 제공되면 외관상이 아니라 컴플라이언스나 안전 실패를 일으키며, 그 무효화 경로가 모두 테스트되어 있습니까? 캐싱은 성능 옷을 입은 정확성 문제입니다. 위험은 느림이 아니라 권한, 잔액, 동의 플래그, 접근 결정이 바뀐 뒤에 제공하는 것입니다. 대규모 조직에서 위험은 분산되어 있습니다. 캐시와 엣지 계층이 팀들에 걸쳐 쌓여 아무도 무엇이 어디에 캐시되었는지, 언제 비워지는지 나열할 수 없기 때문입니다. 긴장은 실제입니다. 공격적 캐싱과 긴 TTL은 지연을 사고 데이터베이스를 보호하지만, 엄격한 신선도는 둘 다 비용이 듭니다. 캐시와 CDN이 제공하는 데이터의 목록을 가져와 컴플라이언스나 안전의 결과를 지닌 항목을 표시하고, 그 각각의 무효화 경로가 단지 설정된 것이 아니라 실제로 실행되었다는 증거를 가져오십시오. 규제되고 공공의 환경에서 오래된 동의나 자격 값은 감사 가능한 실패이므로, 그런 항목은 명시적이고 테스트된 무효화 경로가 필요하거나 아예 캐시하지 않아야 합니다.

  6. 권위 있는 저장소마다 보존, 보관, 데이터 거주 전략은 무엇이며, 감사자에게 입증할 수 있습니까? 데이터는 코드보다 오래 살고 흔히 그것을 쓴 팀보다도 오래 살므로, 무한한 성장과 모호한 거주 규칙은 테이블이 감당 못 하게 되거나 기록이 잘못된 관할에 있게 될 때까지 아무도 소유하지 않는 문제가 조용히 됩니다. 대규모 조직은 많은 저장소와 리전에 걸치며, 상충하는 고려는 비용(핫 스토리지는 비싸니 보관하고 계층화), 성능(부푼 테이블이 모든 것을 느리게 함), 법적 의무(충돌할 수 있는 법정 보존 하한과 거주 상한)입니다. 권위 있는 데이터셋마다 보존 기간, 데이터가 물리적으로 사는 곳, 보관 및 삭제 메커니즘, 책임자의 이름을 가져오십시오. 기업, 특히 정부 시스템에서 보존과 거주는 대개 감사와 주권 요건이 있는 법적 의무이므로, 각 기록이 어디에 사는지, 얼마나 오래 보관되는지, 언제 파기되는지 입증할 수 있는 것은 호의가 아니라 영업 면허입니다.

분야별 관점

스타트업. 데이터베이스 하나를 운영하고 동물원을 피하십시오. 단일 관리형 관계형 저장소는 트랜잭션, 백업할 하나, 일관성을 추론할 한 곳을 주며, 이는 정확히 세 명 규모의 팀이 머릿속에 담을 수 있는 것입니다. 특정한 느린 질의나 실제 읽기 양이 강제할 때만 캐시, 읽기 복제본, 검색 색인을 추가하여 복잡성이 값을 치르는 이유와 함께 오게 하십시오. 첫날부터 이전을 버전 관리하십시오. 운영 중인 제품에 이전 규율을 사후에 도입하는 것이 처음부터 가지는 것보다 훨씬 어렵기 때문입니다.

소기업. 데이터베이스 전문가도 여러 엔진을 운영할 시간도 없으니 관리형 저장소를 선호하고 백업, 패치, 복제를 플랫폼 제공자가 처리하게 하십시오. 저장소 선택을 구매 결정으로 다루십시오. 벤치마크에서 가장 빠른 것이 아니라 도구가 이미 통합되는 지루하고 잘 지원되는 엔진을 고르십시오. 실제로 검증할 수 있는 단순한 보존 및 백업 정책을 정하고, 비우는 명확한 방법 없이는 돈이나 권한과 연결된 어떤 것도 캐시하지 마십시오. 오래된 가격이나 권한은 고객을 잃게 하기 때문입니다.

대기업. 핵심 과제는 많은 팀에 걸친 폴리글랏 영속성입니다. 관계형 기록 시스템에 검색, 캐시, 웨어하우스, 어쩌면 그래프나 시계열 엔진을 더하되 각각 공유가 아니라 서비스가 소유합니다. 유지하는 저장소 전반에서 운영 도구, 백업, 모니터링을 표준화하고, 새 엔진 채택은 높은 기준에 두고, 확장-축소 이전과 명시적 캐시 무효화를 기본으로 만드십시오. 자산을 명확한 데이터 소유권을 가진 포트폴리오로 관리해, 어떤 엔진도 그것을 정당화한 워크로드를 넘어 살아남지 않고 어떤 팀도 공유 데이터베이스로 결합되지 않게 하십시오.

정부. 데이터 거주, 법정 보존, 입증 가능한 무결성이 모든 선택을 형성합니다. 모든 저장소를 주권 리전에 프로비저닝하고, CDN은 개인 정보가 아닌 데이터만 캐시하도록 설정하고, 규제 기관을 위해 재구성 가능해야 하는 기록에는 불변 감사 이력을 유지하십시오. 새 법률이 의무화한 이전은 입법 마감 동안 서비스가 계속 가용하도록 파이프라인을 통해 하위 호환되게 적용해야 하며, 기록 시스템은 어느 값이 법적 원천인지 입증하고 모든 파생 사본을 그것으로부터 재구축할 수 있도록 식별 가능해야 합니다.

사례

스타트업. 시드 단계 스타트업이 모든 것을 단일 관리형 PostgreSQL 인스턴스에서 돌리고, 필요하기 전에 별도의 검색 엔진, 캐시, 웨어하우스를 추가하려는 충동에 저항합니다. 데이터베이스가 하나라는 것은 백업할 것이 하나, 일관성을 추론할 곳이 하나, 그저 동작하는 트랜잭션이라는 뜻이며, 팀 전체가 세 명의 엔지니어일 때 중요합니다. 특정한 느린 질의와 실제 읽기 양이 정당화할 때만 Redis 캐시와 읽기 복제본을 추가해, 복잡성이 앞서서가 아니라 값을 치르는 이유와 함께 옵니다.

대기업. 한 소매 은행은 권위 있는 원장을 강하게 일관된 관계형 데이터베이스에 두고, 모든 기장이 제대로 된 ACID 트랜잭션이며 쓰기 규모를 위해 계좌 범위로 샤딩됩니다. 그 둘레에 폴리글랏 자산이 있습니다. 고객 조회용 검색 색인, 모바일 앱의 계좌 요약용 Redis 캐시(write-through, 짧은 TTL), 규제 및 분석 보고용 컬럼형 웨어하우스, 거래 네트워크 사기 탐지용 그래프 데이터베이스입니다. 원장의 스키마 변경은 이중 쓰기를 곁들인 확장-축소를 써서 24/7 시스템이 이전 때문에 다운타임을 겪지 않습니다.

정부. 한 국가 차량 등록부는 법정 보존과 전체 감사 이력을 갖춘 관계형 기록 시스템에 권위 있는 기록을 저장합니다. 공개된 “차량 조회”는 읽기 복제본과 짧은 TTL의 엣지 캐시에서 제공됩니다. 약간 오래된 공개 데이터는 허용되고 읽기 양이 쓰기를 압도하기 때문입니다. 데이터 거주법이 모든 기록이 국내에 남도록 요구하므로 모든 저장소가 주권 리전에 프로비저닝되고 CDN은 개인 정보가 아닌 데이터만 캐시하도록 설정됩니다. 교통 정책이 의무화한 새 필드 추가 이전은 입법 마감 동안 서비스가 계속 가용하도록 파이프라인을 통해 하위 호환되게 적용됩니다.

비즈니스 사례: 동기, ROI, TCO

데이터 아키텍처 결정은 소프트웨어에서 가장 길고 큰 비용 꼬리를 가진 것 중 하나입니다. 시스템과 통합이 일단 의존하면 데이터와 그 스키마가 바꾸기 가장 어려운 것이기 때문입니다. 좋은 실천(의도적인 저장소 선택, 규율 있는 이전, 설계된 캐싱, 적절한 샤딩)의 도입 비용은 대부분 시니어 엔지니어링 시간과 약간의 추가 운영 도구입니다. 도입하지 않는 비용은 비즈니스 전체를 조이는 과부하된 단일 데이터베이스, 잘못된 저장소를 너무 늦게 발견했을 때의 긴급 재플랫폼, 엉망이 된 이전의 장기 장애, 그리고 가장 해로운 것으로 잘못 무효화된 캐시나 잃은 트랜잭션에서 오는 데이터 손상이나 컴플라이언스 위반으로 나타납니다.

리더십에게는 확장성 여유, 인시던트 위험, 규제 노출의 언어로 논거를 세우십시오. 올바른 저장소 선택이 비즈니스가 재작성 없이 읽기와 쓰기 양을 키울 수 있게 합니다. 규율 있는 이전이 스키마가 다운타임 없이 새 의무를 따라가게 합니다. 올바른 캐싱이 조용한 오래됨 버그 없이 빠른 사용자 경험을 줍니다. 시스템 수명에 걸친 TCO를 정량화하십시오. 잘 고른 단일 데이터 아키텍처는 나쁜 것을 우회하는 반복 비용을 피하며, 예방된 데이터 손상 인시던트 하나는 대개 그것을 잘하는 전체 비용을 압도합니다. 규제 부문에서 데이터 무결성과 거주를 입증하는 능력은 비용 센터가 아니라 영업 면허입니다.

안티패턴과 함정

  • 서비스 간 공유 데이터베이스. 여러 서비스가 하나의 스키마를 읽고 써서 팀을 결합하고 모든 변경을 조율의 위기로 만드는 것.
  • 모든 것을 위한 하나의 데이터베이스. 분석, 큐, 검색, 트랜잭션을 단일 관계형 엔진에 떠넘겨 무너질 때까지 가는 것.
  • 빅뱅 이전. 다운타임이 필요하고 안전하게 롤백할 수 없는 단일 호환 파괴적 스키마 변경.
  • 무효화 전략 없는 캐싱. 오래된 데이터가 무기한 제공되거나, 아무도 캐시가 언제 비워지는지 소유하지 않아 정확성 버그가 생기는 것.
  • 성급한 샤딩. 부하가 요구하기 전에 데이터를 분산해, 이득 없이 조인과 트랜잭션을 영구히 잃는 것.
  • 복제 지연 무시. 지연된 복제본에서 자신의 쓰기를 읽어 오래된 데이터를 받아 사용자 기대를 깨는 것.
  • 무한한 데이터 성장. 보관이나 보존 전략이 없어 성능과 비용이 감당 못 할 때까지 테이블이 커지는 것.
  • 파생 데이터를 진실로 저장. 캐시, 색인, 투영을 기록 시스템으로 다루다 그것이 표류했음을 발견하는 것.

성숙도 모델

  • 1단계: 시작. 하나의 데이터베이스가 모든 목적에 쓰입니다. 스키마 변경은 수동이고 즉흥적이며 이전 규율이 없습니다. 캐싱은 부수적이고 무효화는 사후 생각입니다. 성능 문제는 더 큰 기계를 사서 반응적으로 풀며, 아무도 데이터셋의 기록 시스템을 믿을 만하게 지명하지 못합니다.
  • 2단계: 발전. 일부 저장소 선택은 의도적이고 캐시나 웨어하우스가 나타났지만, 실천은 팀마다 다릅니다. 이전은 버전 관리되지만 가끔 다운타임이 필요하고, 확장-축소는 우연히 아는 사람이 씁니다. 여러 서비스가 여전히 데이터베이스를 공유하고, 캐싱 전략은 팀마다 다릅니다.
  • 3단계: 표준화. 폴리글랏 영속성이 워크로드에 맞추어지고, 각 저장소를 서비스가 소유하며 공유하지 않습니다. 자동화되고 하위 호환되는 무중단 확장-축소 이전이 문서화되고 조직 전체에서 시행되는 표준입니다. 캐싱 전략, TTL, 무효화 경로가 명시적 설계 산출물이며, 각 데이터셋의 단일 기록 시스템이 문서화되고 파생 사본은 그것으로부터 재구축할 수 있습니다.
  • 4단계: 관리. 데이터 자산이 기준선에 대해 측정되고 통제됩니다. 이전 소요 시간과 롤백 비율, 자신의 쓰기 읽기 요구에 대한 복제 지연, 캐시 적중률과 오래됨 인시던트, 저장소별 운영 비용, 목표 백분위수의 질의 지연을 추적하고 숫자에 따라 행동합니다. 보존과 거주가 법정 요건에 대해 감사되고, 파생 데이터의 정확성이 지속적으로 검증되며, 모든 엔진은 그것이 제공하는 워크로드에 대해 비용을 정당화해야 합니다.
  • 5단계: 오케스트레이션. 데이터 아키텍처가 조직 전체의 용량, 비용, 위험 계획과 통합되어 지속적으로 개선됩니다. 샤딩, 캐싱, 일관성 선택은 접근 패턴과 비용이 이동함에 따라 워크로드별로 재균형되고, 더는 자리를 얻지 못하는 저장소는 계획된 이전으로 퇴역합니다. 스키마 진화, 보관, 거주가 완전히 자동화되고 적응적이어서, 자산이 긴급 재플랫폼 없이 새 의무와 부하에 맞추어 스스로 모양을 바꿉니다.

논의를 위한 아이디어

  1. 현재 저장소 중 어느 것이 설계되지 않은 일을 하고 있으며, 맞는 엔진은 무엇이겠습니까?
  2. 오늘 가장 큰 테이블의 스키마 변경을 무중단으로 할 수 있습니까? 아니라면 왜 아닙니까?
  3. 시스템 어디에서 오래됨이 컴플라이언스나 정확성 실패를 일으킬 수 있는 데이터를 캐시하고 있습니까?
  4. 어느 서비스가 데이터베이스를 공유하며, 각자에게 자기 것을 주려면 무엇이 필요합니까?
  5. 쓰기 가능한 단일 데이터베이스가 확장의 천장인 곳은 어디이며, 읽기 복제나 샤딩이 알맞은 다음 단계입니까?
  6. 보존과 보관 전략은 무엇이며, 누가 책임집니까?

핵심 요점

  • 데이터는 코드보다 오래 삽니다. 저장소와 모델링 결정은 시스템의 전 수명 동안 비즈니스를 제약합니다.
  • 각 워크로드를 접근 패턴에 맞는 저장 패러다임에 맞추십시오. 규모에서는 폴리글랏 영속성을 예상하십시오.
  • 각 서비스에 자기 데이터의 소유권을 주십시오. 공유 데이터베이스로 팀을 결합하지 마십시오.
  • 스키마 진화를 지속적인 것으로 다루고 하위 호환되는 무중단 확장-축소 이전을 쓰십시오.
  • 캐싱은 정확성 문제입니다. TTL, 무효화, 스탬피드 방지를 의도적으로 설계하고, 컴플라이언스가 핵심인 데이터는 테스트된 무효화 경로 없이 절대 캐시하지 마십시오.
  • 각 워크로드가 필요로 하는 일관성과 트랜잭션 보장만 사십시오. 샤딩과 복제는 파티션 간 트랜잭션을 규모와 맞바꿉니다.

참고 문헌과 더 읽을거리

  • Martin Kleppmann, Designing Data-Intensive Applications
  • Pramod Sadalage and Martin Fowler, NoSQL Distilled
  • Pramod Sadalage and Scott Ambler, Refactoring Databases: Evolutionary Database Design
  • C. J. Date, An Introduction to Database Systems
  • Joe Celko, SQL for Smarties
  • Vlad Mihalcea, High-Performance Java Persistence (transactions, isolation, concurrency)
  • Eric Evans, Domain-Driven Design (bounded contexts and data ownership)
  • Werner Vogels, “Eventually Consistent”