분산 데이터베이스 (Distributed Database)

분산 데이터베이스는 네트워크로 연결된 여러 컴퓨터 시스템에 물리적으로 분산되어 있지만, 논리적으로는 하나의 데이터베이스처럼 사용자에게 투명하게 제공되는 데이터베이스 시스템이다.  이는 여러 CPU에 연결된 저장장치들을 하나의 데이터베이스 관리 시스템(DBMS)으로 제어하는 형태를 취한다.

예를 들어, 글로벌 전자상거래 기업이 아시아, 유럽, 미주 등 여러 지역에 데이터베이스를 두고 운영하는 경우를 생각해볼 수 있다.

분산 데이터베이스의 구조를 코드로 이해해보자:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# 분산 데이터베이스 시스템의 기본 구조 예시
class DistributedDatabase:
    def __init__(self):
        # 여러 지역의 데이터베이스 노드 설정
        self.nodes = {
            'asia': DatabaseNode('asia-server', replica_set=['asia-1', 'asia-2']),
            'europe': DatabaseNode('europe-server', replica_set=['eu-1', 'eu-2']),
            'americas': DatabaseNode('americas-server', replica_set=['am-1', 'am-2'])
        }
    
    def write_data(self, data, region):
        # 데이터 쓰기 작업 수행
        primary_node = self.nodes[region]
        primary_node.write(data)
        
        # 다른 지역으로 복제
        self._replicate_to_other_regions(data, region)
    
    def read_data(self, query, region):
        # 가장 가까운 노드에서 데이터 읽기
        return self.nodes[region].read(query)

주요 특징

  1. 데이터 분할(Partitioning)
    데이터를 여러 노드에 나누어 저장하는 방식이다.
    수평 분할(Sharding)과 수직 분할이 있다.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    
    class DatabasePartitioner:
        def shard_data(self, data, shard_key):
            # 샤딩 키를 기반으로 데이터 분할
            shards = {}
            for record in data:
                shard_id = self._calculate_shard(record[shard_key])
                if shard_id not in shards:
                    shards[shard_id] = []
                shards[shard_id].append(record)
            return shards
    
        def _calculate_shard(self, key):
            # 해시 기반 샤딩
            return hash(key) % self.num_shards
    
  2. 데이터 복제(Replication)
    데이터의 가용성과 신뢰성을 높이기 위해 여러 노드에 복사본을 유지한다.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    
    class ReplicationManager:
        def __init__(self, nodes):
            self.nodes = nodes
    
        def replicate_data(self, data, source_node):
            # 리더-팔로워 복제 구현
            for node in self.nodes:
                if node != source_node:
                    try:
                        node.replicate(data)
                    except ConnectionError:
                        self._handle_replication_failure(node, data)
    
  3. 일관성 관리(Consistency Management)
    분산된 노드들 간의 데이터 일관성을 유지하는 것이 중요하다.

    1
    2
    3
    4
    5
    6
    7
    8
    
    class ConsistencyManager:
        def ensure_consistency(self, transaction):
            # 2단계 커밋 프로토콜 구현
            prepared_nodes = self._prepare_phase(transaction)
            if len(prepared_nodes) == len(self.nodes):
                return self._commit_phase(transaction, prepared_nodes)
            else:
                return self._abort_phase(prepared_nodes)
    

구현에 사용되는 주요 기술

  1. 합의 알고리즘(Consensus Algorithms)
    Raft나 Paxos와 같은 알고리즘을 사용하여 노드 간 합의를 도출한다.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    
    class RaftConsensus:
        def __init__(self, node_id, nodes):
            self.node_id = node_id
            self.nodes = nodes
            self.current_term = 0
            self.voted_for = None
            self.log = []
    
        def start_election(self):
            self.current_term += 1
            self.voted_for = self.node_id
            # 다른 노드들에게 투표 요청
            votes = self._request_votes()
            return self._check_majority(votes)
    
  2. 분산 트랜잭션(Distributed Transactions)
    여러 노드에 걸친 트랜잭션의 원자성을 보장한다.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    
    class DistributedTransactionManager:
        def execute_transaction(self, transaction):
            try:
                # 트랜잭션 시작
                transaction_id = self._begin_transaction()
    
                # 각 노드에서 작업 실행
                for operation in transaction.operations:
                    self._execute_operation(operation)
    
                # 커밋
                self._commit_transaction(transaction_id)
    
            except Exception as e:
                # 롤백
                self._rollback_transaction(transaction_id)
                raise e
    
  3. 데이터 동기화(Data Synchronization)
    노드 간 데이터를 동기화하는 메커니즘을 제공한다.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    class DataSynchronizer:
        def sync_nodes(self, source_node, target_node):
            # 변경 로그 기반 동기화
            last_sync_point = target_node.get_last_sync_point()
            changes = source_node.get_changes_since(last_sync_point)
    
            for change in changes:
                target_node.apply_change(change)
    
            target_node.update_sync_point(source_node.current_position)
    

구현할 때 고려해야 할 중요한 요소

  1. CAP 이론에 따른 트레이드오프
    일관성(Consistency), 가용성(Availability), 분할 내성(Partition Tolerance) 중 두 가지만 동시에 만족할 수 있다.

  2. 네트워크 지연과 장애
    네트워크 문제로 인한 데이터 동기화 지연이나 노드 간 통신 실패를 고려해야 한다.

  3. 데이터 지역성(Data Locality)
    데이터를 사용자와 가까운 위치에 저장하여 접근 속도를 개선한다.


참고 및 출처