벡터 클락(Vector Clock)은 분산 시스템에서 이벤트들 간의 인과 관계(causality)를 추적하는 논리 시계 메커니즘이다. 물리적 시계의 동기화 문제 없이 이벤트의 순서와 동시성을 정확하게 표현한다. DynamoDB, Riak에서 충돌 감지에 사용된다.
원리
N개 노드: 각 노드는 N개 원소의 벡터 유지
규칙:
1. 로컬 이벤트: 자신의 카운터 증가
Node A: [1,0,0] → [2,0,0]
2. 메시지 전송: 자신의 카운터 증가 후 현재 벡터를 함께 전송
Node A: [2,0,0] 전송
3. 메시지 수신: 각 원소의 최대값 + 자신의 카운터 증가
Node B: [0,1,0] + 수신 [2,0,0] → max = [2,1,0] → [2,2,0]
인과 관계 판단
V(a) < V(b): a가 b보다 먼저 발생 (인과 관계)
조건: V(a)의 모든 원소 ≤ V(b)의 대응 원소, 적어도 하나는 <
V(a) || V(b): 동시 발생 (concurrent, 충돌 가능)
조건: V(a) ≮ V(b) AND V(b) ≮ V(a)
예:
V(A) = [3,2,1], V(B) = [4,2,1] → A < B (인과)
V(A) = [3,2,1], V(B) = [2,3,1] → A || B (동시)
python
class VectorClock:
def __init__(self, node_id: str, nodes: list):
self.node_id = node_id
self.clock = {node: 0 for node in nodes}
def tick(self):
self.clock[self.node_id] += 1
return dict(self.clock)
def update(self, received: dict):
for node, ts in received.items():
self.clock[node] = max(self.clock.get(node, 0), ts)
self.clock[self.node_id] += 1
def happens_before(self, other: dict) -> bool:
return (all(self.clock.get(n, 0) <= other.get(n, 0) for n in set(self.clock)|set(other))
and any(self.clock.get(n, 0) < other.get(n, 0) for n in set(self.clock)|set(other)))
def concurrent(self, other: dict) -> bool:
return not self.happens_before(other) and not all(
other.get(n,0) <= self.clock.get(n,0) for n in set(self.clock)|set(other))
| 항목 | 람포트 타임스탬프 | 벡터 클락 |
|---|
| 크기 | O(1) | O(N) |
| 인과 관계 | 단방향만 (a<b이면 ts(a)<ts(b)) | 양방향 (동시성 감지 가능) |
| 동시성 탐지 | 불가 | 가능 |
관련 개념