260. 스플릿 브레인 (Split Brain) 현상
핵심 인사이트 (3줄 요약)
- 본질: 스플릿 브레인(Split Brain)은 네트워크 분단으로 인해 두 개의 노드 또는 노드 그룹이 서로通信할 수 없게 되어, 각각이 자신이 유일한 Master/Primary라고 잘못 인식하게 되는 현상이다.
- 가치: 스플릿 브레인이 발생하면 두 노드가 동시에 쓰기를 수행하여 데이터 불일치가 발생할 수 있으므로, 이를防止하기 위한 Quorum/과반수 투표 등의 메커니즘이 필수적이다.
- 융합: CAP 정리, Consensus 알고리즘, 복제 전략, ZooKeeper, 2PC와 밀접하게 연관되며, 분산 데이터베이스와 캐시 시스템에서 핵심적인 고려사항이다.
Ⅰ. 개요 및 필요성 (Context & Necessity)
개념 정의
스플릿 브레인(Split Brain)은 분산 시스템에서 네트워크 분단(Network Partition)이나 통신 장애로 인해 두 개의 노드 그룹이 서로通信할 수 없게 되었을 때, 각 노드 그룹이 자신이唯一の Master/Primary라고 생각하게 되는 현상이다. 이 상태에서 두 개의 Master가 동시에 쓰기를 수행하면 데이터 불일치(데이터 충돌)가 발생한다.
필요성
스플릿 브레인은 분산 시스템에서 가장 위험한 장애 상황 중 하나이다. 두 개의 Master가 동시에 존재하면, 쓰기 충돌이 발생하고 시스템이分裂된다. 이를防止하기 위해 Quorum 기반 투표, fencing, 장애 감지 메커니즘 등이 필수적으로 설계되어야 한다. 이러한 보호 메커니즘이 없다면, 스플릿 브레인으로 인한 데이터 손상이나 불일치가 발생할 수 있다.
배경
스플릿 브레인은 1970년대부터 알려진 문제로,初期에는 금융 시스템의 중앙 처리 장치(主机)와백업 시스템 사이의 통신 장애에서 비롯되었다. 이후 분산 데이터베이스, 클러스터 시스템, 컨테이너 오케스트레이션(Kubernetes) 등 다양한 분산 시스템에서 중요한 고려사항으로 자리잡았다.
비유
스플릿 브레인은 두 개의 공장이 동시에 같은 제품을 생산하면서 각각 "내가正统한 공장"이라 주장하는 상황과 같다. 만약 두 공장이 서로 통보 없이 생산하면 재고 관리가崩溃하고, 고객에게 중복 발송되는 등의 문제가 발생한다.
📢 섹션 요약: 스플릿 브레인은 네트워크 분단으로 두 노드가 서로通信 불가능할 때 각각이 Master라고 인식하여 동시에 쓰기를 수행하는 위험한 현상으로, Quorum/과반수 투표 등으로防止해야 한다.
Ⅱ. 아키텍처 및 핵심 원리 (Deep Dive)
스플릿 브레인 발생 과정
┌─────────────────────────────────────────────────────────────────────────────┐
│ 스플릿 브레인 발생 과정 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ [정상 상태] │
│ │
│ ┌──────────┐ 통신 ┌──────────┐ │
│ │ Node A │ ◀───────▶ │ Node B │ │
│ │ (Master) │ │ (Backup) │ │
│ └──────────┘ └──────────┘ │
│ │
│ ※ A가 Master, B가 Backup (A가 모든 쓰기를 처리) │
│ │
│ [네트워크 분단 발생] │
│ │
│ ┌──────────┐ ✕ 분단 ┌──────────┐ │
│ │ Node A │ ◀───────✕──▶ │ Node B │ │
│ │ (Master) │ 통신 단절 │ (Backup) │ │
│ └──────────┘ └──────────┘ │
│ │
│ [스플릿 브레인 발생] │
│ │
│ ┌──────────┐ ┌──────────┐ │
│ │ Node A │ │ Node B │ │
│ │ (Master │ │ (Master!)│ │
│ │ 인식) │ │ (인식) │ │
│ └──────────┘ └──────────┘ │
│ │
│ ※ A는 B가死亡했다고 판단 │
│ ※ B도 A가死亡했다고 판단 (양쪽 모두 상대방이死了고 생각) │
│ ※ 각자 자신이 Master라고宣言하여 쓰기 受入れ开始 │
│ │
│ [데이터 불일치 발생] │
│ │
│ Node A: 쓰기 #1 → value = "Kim" │
│ Node B: 쓰기 #1 → value = "Lee" (동시에 다른 값 기록) │
│ │
│ ※ 분단 복구 후: 어떤 값이正しいか? (데이터 충돌) │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
[다이어그램 해설] 스플릿 브레인의 핵심 문제는 "네트워크 장애"와 "노드 장애"를 구분할 수 없다는 것이다. 노드가 응답하지 않는 이유는 (1) 진짜故障또는 (2) 네트워크 분단으로通信不可인 경우 두 가지이다. Heartbeat Timeout만으로는 이를 구분할 수 없으므로, Quorum 기반 투표나 fencing 메커니즘이 필요하다.
스플릿 브레인 방지를 위한 메커니즘
┌─────────────────────────────────────────────────────────────────────────────┐
│ 스플릿 브레인 방지를 위한 메커니즘 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. Quorum (과반수) 투표 │
│ ─────────────────────────── │
│ • 쓰기는 과반수(Majority) 이상의 노드에서承認되어야 Commit │
│ • 네트워크 분단 발생 시, 과반수를 확보한 쪽만 쓰기 수행 │
│ • 과반수를 확보하지 못한 쪽은 읽기 전용 또는 쓰기 거부 │
│ │
│ 예: 5개 노드 클러스터 │
│ ├── 분단 A (3개 노드): 과반수 확보 → 쓰기 허용 │
│ └── 분단 B (2개 노드): 과반수 미달 → 쓰기 거부 │
│ │
│ 2. fencing (펜싱) │
│ ───────────────── │
│ • 각 쓰기에 고유한 버전/时代号 부여 │
│ • 쓰기가受理되면 해당 자원에 "락"을 획득 │
│ • 다른 노드의 쓰기 시도는 "락 없음"으로 거부 │
│ • 예: ZooKeeper의 zxid, HDFS의Block IDs │
│ │
│ 3. 리더 임명 (Leader Election) │
│ ───────────────────────── │
│ • Consensus 알고리즘 (Raft, Paxos)을 통해 단일 리더 보장 │
│ • 임의의 타이머/높은 Term 번호 등으로 충돌 최소화 │
│ • 두 개의 리더가 동시에 존재하지 않도록 보장 │
│ │
│ 4. 스토리지 퍼시스턴스 │
│ ───────────────────── │
│ • 쓰기 전에 디스크에 기록 (WAL 등) │
│ • 장애 복구 시 이전 상태에서 복구 │
│ • 예: ZooKeeper의 트랜잭션 로그 │
│ │
│ 5. 자동 장애 복구 (Auto-Failover) │
│ ──────────────────────────── │
│ • 장애 감지 시 자동으로备用 시스템으로 전환 │
│ • 전환 전 fencing token 발급으로 중복 실행 방지 │
│ • 예: Kubernetes의 Pod Disruption Budget │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
[다이어그램 해설] Quorum 기반 방식은 가장 널리 사용되는 스플릿 브레인 방지 메커니즘이다. 5개 노드 클러스터에서 3개 이상의 노드가Agreement하면 쓰기를Commit한다. 네트워크 분단으로 3개와 2개로分裂되면, 3개 쪽만 쓰기를 계속하고 2개 쪽은 읽기 전용 또는 쓰기 거부 상태가 된다. 이렇게 하면 두 곳에서 동시에 쓰기가 발생하는 것을防止할 수 있다.
Cassandra의 Tunable Consistency와 스플릿 브레인
┌─────────────────────────────────────────────────────────────────────────────┐
│ Cassandra의 스플릿 브레인 방지 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Cassandra는 Quorum 기반 Consistency Level를 통해 스플릿 브레인을 방지한다. │
│ │
│ [노드 수: 5, Consistency Level: QUORUM (3)] │
│ │
│ 쓰기 동작: │
│ ──────── │
│ • 쓰기 시 3개 이상의 노드에 기록해야 성공 │
│ • 네트워크 분단 발생 시 3개 미만의 노드에 기록 가능 │
│ • → 3개 미만의 기록은 성공으로 반환되지 않음 (예외 발생) │
│ • → 과반수 미만의 쓰기는 실패하므로 스플릿 브레인防止 │
│ │
│ 읽기 동작: │
│ ──────── │
│ • QUORUM 읽기 시 3개 이상의 노드에서 읽기 │
│ • 가장 최신 데이터 반환 (Timestamp 기반) │
│ • 분단 시에도 과반수에서 읽으면 일관된 데이터 획득 가능 │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ 네트워크 분단 시 Cassandra 동작 │ │
│ │ │ │
│ │ 분단 A (3개 노드): QUORUM(3) 충족 → 읽기/쓰기 가능 │ │
│ │ 분단 B (2개 노드): QUORUM(3) 미달 → 쓰기 거부, 읽기는 가능 but陈旧 │ │
│ │ │ │
│ │ ※ 스플릿 브레인防止! │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
[다이어그램 해설] Cassandra에서 QUORUM 미만의 쓰기는 실패로 처리된다. 이는 네트워크 분단 시에도 과반수 이상의 노드에서만 쓰기가Commit됨을 보장한다. 따라서 스플릿 브레인이 발생하더라도 두 곳에서 동시에 쓰기가Commit되는 것은防止된다. 다만 분단 B에서는 읽기만 가능하고 그 데이터도最新でない 수 있다는点是 注意해야 한다.
fencing Token 예시
┌─────────────────────────────────────────────────────────────────────────────┐
│ fencing Token 예시 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ [fencing 없음: 스플릿 브레인 발생] │
│ │
│ Time T1: Node A가 쓰기 #1 수행 (value = "Kim") │
│ Time T2: 네트워크 분단 발생 │
│ Time T3: Node B가 쓰기 #1 수행 (value = "Lee") │
│ Time T4: 네트워크 복구 │
│ Time T5: 어떤 값이正しいか? → 충돌! │
│ │
│ [fencing 있음: 스플릿 브레인 방지] │
│ │
│ Time T1: Node A가 락 획득 (token: 100), 쓰기 #1 수행 │
│ Time T2: 네트워크 분단 발생 │
│ Time T3: Node B가 락 획득 시도 → 실패 (Node A가 락 보유 중) │
│ ※ Node B는 쓰기를 수행할 수 없음 │
│ Time T4: 네트워크 복구 │
│ Time T5: Node A의 쓰기만 존재 → 충돌 없음 │
│ │
│ ZooKeeper의 zxid (Transaction ID): │
│ • 각 트랜잭션에 고유한 ID 부여 │
│ • Leader 변경 시마다 증가 │
│ • 낮은 zxid의 쓰기는自動的に無効화 │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
📢 섹션 요약: 스플릿 브레인 방지를 위해 Quorum 투표, fencing, Consensus 알고리즘, 스토리지 퍼시스턴스 등의 메커니즘을 조합하여使用해야 하며, 단일 메커니즘만으로는 完全 방지가 어렵다.
Ⅲ. 구현 및 실무 응용 (Implementation & Practice)
ZooKeeper의 fencing
// ZooKeeper에서 fencing을利用한 스플릿 브레인 방지
// 1. ZooKeeper를利用した分散ロック
public class DistributedLock {
private ZooKeeper zk;
private String lockPath;
// 락 획득
public boolean acquire() throws Exception {
// 고유한 임시 노드 생성
String path = zk.create(lockPath + "/lock-",
null,
ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL_SEQUENTIAL);
// 시퀀스 번호 확인하여 가장 작은 번호이면 락 획득
List<String> children = zk.getChildren(lockPath, false);
Collections.sort(children);
if (path.equals(lockPath + "/" + children.get(0))) {
return true; // 락 획득 성공
}
// 가장 작은 번호가 아니면 이전 번호의 watch 등록
String prevPath = lockPath + "/" +
children.get(Collections.binarySearch(children,
path.substring(path.lastIndexOf("/") + 1)) - 1);
// ...
}
}
// 2. fencing token 활용
public class FencingClient {
private long fencingToken = 0;
public void write(String data) throws Exception {
// 쓰기 직전에 fencing token 획득
fencingToken = zk.getFencingToken();
// fencing token과 함께 쓰기 수행
storage.write(data, fencingToken);
}
}
Kubernetes의 스플릿 브레인 방지
# Kubernetes: Pod Disruption Budget (PDB)를利用한 스플릿 브레인 방지
# 1. Pod Disruption Budget 설정
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
name: my-app-pdb
spec:
# 최소한 2개의 Pod이 항상 利用可能해야 함
minAvailable: 2
selector:
matchLabels:
app: my-app
# 2. 노드 장애 시 자동 복구
# Kubernetes는 기본적으로 3개 이상의 복제본을 권장하며,
# Quorum 기반 Leader 선출을 통해 스플릿 브레인을 방지한다.
# 3. etcd의 Raft Consensus 활용
# Kubernetes는 etcd를 통해 클러스터 상태를 관리하며,
# etcd의 Raft 알고리즘이 스플릿 브레인을 방지한다.
스플릿 브레인 발생 시 대응 절차
┌─────────────────────────────────────────────────────────────────────────────┐
│ 스플릿 브레인 발생 시 대응 절차 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 단계 1: 탐지 및 확인 │
│ ────────────────── │
│ • 모니터링 시스템에서 두 개의 Master 감지 │
│ • 각 Master의 로그 및 메타데이터 비교 │
│ • 스플릿 브레인 발생 시각 및 범위 확인 │
│ │
│ 단계 2: 상황 평가 │
│ ────────────── │
│ • 어느 쪽이 더 최신 데이터를 보유하고 있는지 확인 │
│ • 데이터 충돌의 심각도 평가 │
│ • 서비스 영향 범위 확인 │
│ │
│ 단계 3: 복구 결정 │
│ ────────────── │
│ • 더 최신 데이터를 보유한 쪽을 Master로 유지 │
│ • 다른 쪽은 읽기 전용 또는 서비스 중단 │
│ • 필요시 수동 머징 (애플리케이션 수준) │
│ │
│ 단계 4: 복구 실행 │
│ ──────────── │
│ • Master 전환 │
│ • 데이터 동기화 │
│ • 정상 작동 확인 │
│ │
│ 단계 5: 사후 분석 │
│ ──────────── │
│ • 스플릿 브레인 발생 원인 분석 │
│ • 방어 메커니즘 강화 │
│ • 유사 발생防止를 위한 개선사항 도출 │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
📢 섹션 요약: 스플릿 브레인 발생 시 탐지, 평가, 복구 결정, 복구 실행, 사후 분석의 체계적 대응 절차가 필요하며, 사전에 방어 메커니즘(Quorum, fencing 등)을 설계하는 것이 필수적이다.
Ⅳ. 품질 관리 및 테스트 (Quality & Testing)
스플릿 브레인 테스트
┌─────────────────────────────────────────────────────────────────────────────┐
│ 스플릿 브레인 관련 품질 테스트 항목 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ [네트워크 분단 시뮬레이션 테스트] │
│ ───────────────────────────── │
│ □ 두 노드 그룹 간 네트워크 연결 차단 │
│ □ 분단 기간 중 양쪽 Master 선출 여부 확인 │
│ □ Quorum 미달 쪽의 동작 확인 (쓰기 거부/읽기 전용) │
│ □ 분단 복구 후 데이터 동기화 동작 확인 │
│ │
│ [동시 쓰기 테스트] │
│ ────────────── │
│ □ 스플릿 브레인 상황에서 양쪽 Master의 동시 쓰기 테스트 │
│ □ 쓰기 충돌 감지 및 해결 방식 확인 │
│ □ 데이터 무결성 위반 여부 확인 │
│ │
│ [복구 테스트] │
│ ─────────── │
│ □ 네트워크 분단 복구 후 Master 전환 동작 확인 │
│ □ 데이터 불일치 해소 과정 확인 │
│ □ 서비스 정상화 시간 측정 │
│ │
│ [장애 감지 테스트] │
│ ───────────────── │
│ □ Heartbeat 타임아웃 설정값 검증 │
│ □ 짧은 타임아웃 vs 긴 타임아웃의 트레이드오프 확인 │
│ □ 진짜 노드 장애 vs 네트워크 분단 구분 가능 여부 │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
📢 섹션 요약: 스플릿 브레인 테스트는 네트워크 분단 시뮬레이션, 동시 쓰기, 복구, 장애 감지 등을 포함해야 하며, 실제 환경에서 발생할 수 있는 다양한 시나리오를 사전에 검증해야 한다.
Ⅴ. 최신 트렌드 및 결론 (Trends & Conclusion)
자동화된 스플릿 브레인 방지
최근에는 스플릿 브레인 방지가 더욱 자동화되고 있다. Kubernetes의 Pod Disruption Budget, Cassandra의 Tunable Consistency, etcd의 Raft Consensus 등이 대표적이다. 이러한 시스템들은 자동으로 Quorum을 관리하고, 장애 시 자동으로故障node를 격리한다.
Regions 간 분산
클라우드 환경에서 Regions 간 분산이 일반화되면서, 스플릿 브레인의 범위가 데이터 센터 단위로 확대되고 있다. AWS Aurora, Google Spanner, CockroachDB 등은 이러한Regions 간 분산 환경에서도 스플릿 브레인을 방지하는 메커니즘을 갖추고 있다.
결론
스플릿 브레인은 분산 시스템에서 가장 위험한 장애 상황 중 하나이다. Quorum 기반 투표, fencing, Consensus 알고리즘 등을 통해防止해야 하며,万一 발생 시에는 체계적인 대응 절차가 필요하다. 시스템을 설계할 때 스플릿 브레인 시나리오를 반드시 고려하고, 적절한 방어 메커니즘을 설계해야 한다.
📢 섹션 요약: 스플릿 브레인은 분산 시스템에서 네트워크 분단 시 두 Master가 동시에 쓰기를 수행하는 위험한 현상으로, Quorum, fencing, Consensus 알고리즘 등으로防止해야 하며, 체계적 대응 절차가 필요하다.
핵심 인사이트 ASCII 다이어그램 (Concept Map)
┌─────────────────────────────────────────────────────────────────────────────┐
│ Split Brain Concept Map │
│ │
│ ┌───────────────────────────┐ │
│ │ Split Brain │ │
│ │ (스플릿 브레인) │ │
│ └─────────────┬─────────────┘ │
│ │ │
│ ┌──────────────────┼──────────────────┐ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 네트워크 │ │ Quorum │ │ Fencing │ │
│ │ 분단 발생 │ │ (과반수) │ │ Token │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 방어 메커니즘 │ │
│ │ Consensus (Raft/Paxos) | 스토리지 퍼시스턴스 | 자동 장애복구│ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 관련 기술: Cassandra, ZooKeeper, etcd, Kubernetes, CockroachDB │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
참고
- 스플릿 브레인은 네트워크 분단으로 두 노드가 서로通信 불가능할 때 발생한다.
- Quorum/과반수 투표, fencing, Consensus 알고리즘 등으로防止해야 한다.
- 단일 메커니즘만으로는完全 방지가 어렵고, 다중 방어 전략이 필요하다. -万一 발생 시 체계적 대응 절차(탐지, 평가, 복구, 사후 분석)가 필수적이다.