Backend
home
✏️

6. 분산 관계형 데이터베이스

생성일
2025/02/18 12:40
태그

Distributed Relational Database(분산 관계형 데이터베이스)

분산 관계형 데이터베이스
Distributed Database가 중점

참고 시나리오

초기에는 단일 테이터베이스 사용
간단한 구조의 Article Table 만든다. Client는 단일한 DB에서 데이터를 생성/조회/수정/삭제한다.
서비스가 활성화되면 단일한 DB로 처리하기엔 큰 부담이 생기게 된다. 저장해야 할 데이터와 트래픽이 많아졌다면 어떻게 해야할까?
가장 간단한 방법으로 Scale-Up을 고려해볼 수 있다. DB 장비의 성능을 업그레이드 한다.
만약에 저장해야 할 데이터와 트래픽이 계속 많아진다면 다시 한 번 Scale-Up을 고려해볼 수 있으나 장비를 무한정 Scale-Up 하는 것은 한계가 있다.
이제 2대의 DB가 운용되며 Client의 요청은 각 DB로 분산될 수 있다.
데이터베이스에 대한 하나의 분산 시스템이 구성된 것이다.
그렇다면, 데이터는 각 DB에 어떻게 분산될 수 있을까?
샤딩을 이용하여 데이터를 여러 DB에 분산할 수 있다.
샤딩된 각각의 데이터 단위를 샤드라고 부른다.
샤딩(Sharding) : 데이터를 여러 데이터베이스에 분산하여 저장하는 기술
샤드(Shard) : 샤딩된 각각의 데이터 단위
샤딩에는 수직 샤딩(Vertical Sharding)과 수평 샤딩(Horizontal Sharding)이 있다.
수직 샤딩(Vertical Sharding) : 데이터를 수직으로 분할하는 방식(컬럼 단위)
article_id 식별자를 이용하여 좌측 샤드 title/content, 우측 샤드 board_id/created_at 을 분산 저장
각 샤드가 적은 수의 컬럼을 저장하므로, 성능 및 공간에 대한 이점이 생긴다.
하지만, 데이터의 분리로 인해 조인 또는 트랜잭션 관리가 복잡해질 수 있다. 수직으로 분할되므로 수평적 확장에 제한이 있다. 수평으로 분할되므로 수평적 확장에 용이하다.
수평 샤딩(Horizontal Sharding) : 데이터를 수평으로 분할하는 방식(행 단위)
좌측 샤드 article_id=1~5000
우측 샤드 article_id=5001~10000으로 분산 저장
각 샤드에 데이터가 분산 저장되므로 성능 및 공간에 대한 이점이 생긴다.
하지만, 데이터의 분리로 인해 조인 또는 트랜잭션 관리가 복잡해질 수 있다.

수직 샤딩, 수평 사딩

수직 샤딩
수평 샤딩
샤딩
수직으로 분할(컬럼 단위)
수평으로 분할(행 단위)
확장성
제한
용이
장점
각 샤드로 데이터 분산되므로, 성능 및 공간에 대한 이점
각 샤드로 데이터 분산되므로, 성능 및 공간에 대한 이점
단점
조인 또는 트랜잭션 관리 등의 어려움
조인 또는 트랜잭션 관리 등의 어려움

Range-based Sharding(범위 기반 샤딩)

데이터를 특정 값(Shard Key)의 특정 범위에 따라 분할하는 기법
좌측 샤드 article_id = 1 ~ 5000
우측 샤드 article_id = 5001 ~ 10000
범위 데이터 조회에 유리
article_id=100 부터 30개 조회한다면 좌측 샤드에서 모든 데이터를 찾을 수 있음
데이터 쏠림 현상 발생 가능
데이터가 6,000개만 있다면, 우측 샤드에는 1,000개만 저장

Hash-based Sharding(해시 기반 샤딩)

데이터를 특정 값(Shard Key)의 해시 함수에 따라 분할하는 기법
hash_function = article_id → article_id % 2 라고 한다면?
좌측 샤드 article_id = 1, 3, 5, …
우측 샤드 article_id = 2, 4, 6, …
균등한 분산을 위한 Shard Key와 해시 함수가 필요
균등하게 분산되지 않으면, 데이터 쏠림 현상 발생 가능
만약, board_id가 Shard Key라고 한다면?
인기 많은 게시판에 데이터가 몰릴 수 있음
범위 데이터 조회에 불리할 수 있음
shard_key = article_id 인 상황에 게시판의 게시글 목록을 조회하려면?
article_id 기준으로 데이터가 분산되었기 때문에 모든 샤드에 요청해야 할 수도 있음
시스템 특성에 따라서 적절한 Shard Key와 해시 함수를 선정해야 함

Directory-based Sharding

디렉토리를 이용하여 데이터가 저장된 샤드를 관리하는 기법
매핑 테이블을 이용하여 각 데이터가 저장된 샤드를 관리
좌측 샤드 article_id = 1, 4
우측 샤드 article_id = 2, 3
디렉토리 관리 비용 있으나, 데이터 규모에 따라 유연한 관리 가능

물리적 샤드와 논리적 샤드

— 물리적 샤드 —
위 그림에서는 DB가 2대로 물리적으로 분리되었다. 2개의 물리적 샤드(Physical Shard)를 가지는 것이다.
물리적 샤드가 2개인 위 상황에서 Hash-based Sharding을 적용한다. 2개의 샤드에 균등한 분산을 위해 아래와 같은 해시 함수를 적용한다.
hash_function = article_id → article_id % 2
8개의 데이터는 2개의 샤드에 4개씩 균등하게 분산되었다.
늘어난 4개의 샤드에 균등한 분산을 위해 아래와 같은 해시 함수를 적용한다.
hash_function = article_id → article_id % 4
article_id = 3, 7, 4, 8은 데이터 재배치가 필요하다.
8개의 데이터 중 4개의 데이터가 새로운 샤드로 균등하게 재배치되었다.
Client는 이제 4개의 Shard로 요청해야 하므로, 애플리케이션 코드를 수정하는 등 새로운 Shard의 정보를 알아야 한다.
데이터베이스의 확장(변경)으로 인해 Client의 수정도 필요했는데 Client와 데이터베이스는 독립적으로 구성 및 운영될 수 있는 시스템이다.
혹시 Client의 수정 없이 DB만 유연하게 확장하는 방법은 없을까? → 논리적 샤드 활용
— 논리적 샤드 —
다시 처음으로 돌아가보면 물리적 샤드는 여전히 2개다.
이번에는 실제 물리적인 샤드의 개수와 관계없이, 개념적으로 데이터를 분할하는 가상의 샤드가 4개 있다고 가정한다. 물리적 샤드는 2개 뿐이지만, Client는 4개의 샤드가 있다고 가정하여 분리하는 것이다.
이러한 가상의 샤드를 논리적 샤드라고 한다.
물리적으로 2개의 샤드로 분산되지만, Client는 4개의 샤드로 분산된 것으로 인지한다.
Client는 논리적 샤드의 접근 방법으로만 DB에 연결하는 것이다.
hash_function = article_id → article_id % 4
그렇다면, Client가 요청한 논리적 샤드가 어떤 물리적 샤드에 속해있는지를 알아야 한다. 그래야 직접적으로 데이터에 접근할 수 있기 때문이다. 이러한 라우팅을 위한 라우터는 DB 시스템 내부 또는 DB와 Client를 연결해주는 중간에 독립적으로 만들어질 수 있다.
여기서 이러한 Router가 DB 시스템 내부에 포함된다고 가정한다. DB 시스템 내부에 존재하는 논리적 샤드의 실제 물리적 샤드로 라우팅해주는, Shard Router를 만들어본다.
Client는 논리적 샤드를 기반으로 Router에 요청하면, DB 시스템 내부의 Router는 물리적 샤드로 라우팅해준다.
예를 들어, article_id = 5 데이터를 요청하려면?
Client 입장에서는 4개의 논리적 샤드가 있으므로 5 % 4 = 1번 샤드로 Router에 요청한다.
Router는 1번 논리적 샤드에 대한 요청을 받아서, 좌측 물리적 샤드로 라우팅한다.
데이터베이스 확장이 필요한 상황이 와서 물리적 샤드를 4개로 늘린다고 가정해보자. 논리적으로 4개의 샤드로 분산되어 있지만, 물리적 샤드가 늘어남에 따라 데이터를 물리적으로 다시 재배치할 수 있다.
4개의 물리적 샤드로 데이터가 재배치되었다.
Router가 물리적으로 늘어난 새로운 샤드 정보를 알도록 한다. 이번에 Client는 어떠한 수정도 필요 없었다. 새로운 물리적 샤드를 알 책임이 있는 Router는 DB 시스템 내부에 있었기 때문이다.
논리적 샤드 개념을 이용하여, 물리적 샤드를 확장하더라도 Client의 어떠한 변경도 없이 DB를 유연하게 확장할 수 있었던 것이다.
물리적 샤드
논리적 샤드
정의
데이터를 물리적으로 분산한 실제 단위
데이터를 논리적으로 분산한 가상의 단위
필요성
대규모 데이터 분산 저장 및 성능 향상
물리적 확장 시, Client 변경 없이 유연한 매핑

데이터 복제 - 고가용성, 안정성, 성능

좌측 샤드에 장애가 발생했다. 시스템 오류 또는 네트워크 순단에 의한 일시적인 현상일 수도 있고, 자연 재해에 의한 영구적인 데이터 손실일 수도 있다.
그럼 좌측 샤드의 데이터는 복구 전까지 또는 영구적으로 사용할 수 없는 것일까?
이러한 문제를 해결하기 위해 데이터 복제본을 관리할 수 있다. Primary(주 데이터베이스)에 데이터를 쓰고, Replica(복제본)에 데이터를 복제한다. Primary/Replica, Leader/Follower, Master/Slave, Main/Standby 등 유사한 개념이지만, 시스템이나 목적에 따라 다르게 사용되기도 한다.
이러한 복제는 동기적 또는 비동기적으로 처리될 수 있다.
Synchronous(동기적): 데이터 일관성을 보장하나, 쓰기 성능이 저하된다.
Asynchronous(비동기적): 쓰기 성능은 유지되나, 복제본에 최신 데이터가 즉시 반영되지 않을 수 있다.
이러한 복제본은 고가용성을 위해 동일한 데이터 센터 내에 관리될 수도 있고, 다른 지역의 데이터 센터에서 관리될 수도 있다. 이러한 데이터의 분산을 통해 데이터는 안전하게 관리된다.
이제 좌측 샤드에 장애가 발생하더라도?
Replica에서 데이터 조회를 수행할 수도 있고,
Replica를 Primary로 재선출하여 쓰기 작업을 이어서 수행할 수도 있다.
이러한 시스템을 통해, 고가용성(Primary 재선출을 통한 서비스 지속성), 데이터 유실 방지 및 데이터 백업(Replica 복제본 관리), 부하 분산(Replica 또는 각 샤드로 요청 분산) 등의 다양한 이점을 가질 수 있다.
Distributed가 무엇인지 학습했지만..
이러한 환경이 구축되어 있다고 가정만 한다.
안정성, 고성능, 고가용성, 내결함성, 확장성 등이 보장된 환경
우리는 서버 애플리케이션 개발이 주 목적
우리의 개발 환경에서는 단일 MySQL을 사용한다.
Docker로 세팅한다.
Sharded 환경을 어느 정도 고려해서 개발한다.