[Design] 분산 데이터 (2)
지극히 주관적인 요약
리더 없는 복제
초기 복제 데이터 시스템은 대부분 리더가 없었다. 리더 없는 복제는 아마존이 내부 Dynamo 시스템에서 사용한 후 다시 DB용 아키텍쳐로 유행했다. 리악, 카산드라, 볼드모트는 다이나모에서 영감을 얻은 리더 없는 복제 모델의 오픈소서 데이터 스토어로, 이런 종류의 데이터베이스를 다이나모 스타일이라 한다.
리더 없는 복제 구현은 다음과 같은 방식으로 구성된다.
- 클라이언트가 여러 복제 서버에 쓰기를 직접 전송
- 또는 코디네이터 노드가 내부적으로 복제 작업을 수행
이 두 경우 모두 리더가 있는 복제와 다르게 특정한 순서로 쓰기작업을 수행하지 않는다. 이러한 구현방식은 데이터베이스마다 다르다.
노드가 다운되었을때 데이터베이스에 쓰기
리더 없는 설정에서는 장애 복구가 필요하지 않다.
<그림>
클라이언트는 여러 노드에 쓰기 요청을 보내는데 어느 수준 이상이면 모든 노드에 직접 쓰지 않아도 된다. 그러면 다운된 노드를 포함하여 일부 데이터는 오래된 값을 가지고 있게 된다. 읽기 요청의 경우 병렬로 여러 노드에 데이터를 요청하고, 그 중 최신의 값을 사용한다.
읽기 복구와 안티 엔트로피
모든 복제서버에 데이터가 복사된 것을 보장하기 위해 다음과 같은 방법을 사용한다.
- 읽기 복구 - 클라이언트가 여러 노드에서 병렬 읽기를 수행하면 오래된 응답을 감지할 수 있다. 클라이언트는 오래된 복제서버에 새로운 값을 다시 기록하여 최신의 상태를 유지할 수 있으며, 이러한 방식은 읽기 작업이 많은 상황에 적합하다.
- 안티 엔트로피 처리 - 백그라운드 프로세스를 두고 복제 서버 간 데이터 차이를 지속적으로 찾아 누락된 데이터를 하나의 복제 서버에서 다른 서버로 복사한다. 이 안티 엔트로피 처리는 특정 순서로 쓰기를 복사하기 때문에 데이터 복사까지 상당한 지연이 발생할 수 있다.
모든 시스템이 이 두 메커니즘을 모두 구현하는 것은 아니다. 안티 엔트로피를 사용하지 않으면 거의 읽지 않는 값은 복제본에서 누락되 내구성이 떨어진다.
읽기와 쓰기를 위한 정족수
리더 없는 서버에서 몇개까지 서버를 쓰거나 읽어야 올바른 값을 가져올 수 있는지가 궁금한다. 클라이언트가 여러 노드에서 데이터를 가져올 때 항상 최신 값을 하나라도 포함한다면 잘못된 데이터를 가져올 일은 없어진다. 이를 일반화 하면 다음과 같다.
- 전체 노드의 수 : n
- 쓰기 성공 노드 수 : w
- 읽기 성공 노드 수 : r
- w + r > n 인 경우, 최소한 r개의 노드 중에서 최신 값을 읽을 수 있다.
이러한 w, r을 따르는 값을 정족수 읽기와 쓰기라 부른다. 다 정확히는 엄격한 쿼럼/정족수strict quorum 이라고 부른다.
- w<n 이면 노드 하나를 사용할 수 없어도 여전히 쓰기 가능
- r<n 이면 노드 하나를 사용할 수 없어도 여전히 읽기 가능
- n=3, w=2, r=2 이면 노드 1개의 장애까지 용인한다.
- n=5, w3, r=3 이면 노드 2개까지의 장애를 용인한다.
- 일반적으로 읽기와 쓰기는 항상 모든 n개의 복제서버에 병렬로 전달하고 w, r은 얼마나 많은 노드를 기다릴지 결정한다.
<그림>
필요한 w나 r의 노드보다 사용 가능한 노드가 적다면 쓰기나 읽기는 에러를 반환한다.
정족수 일관성의 한계
보통 r과 w의 값으로 노드의 과반수 초과(n/2)를 선택한다. 이유는 n/2노드 장애까지 허용해도 w + r > n이 보장되기 때문이다. 하지만 정족수가 다수일 필요는 없다?? 읽기와 쓰기 동작에서 사용하는 노드 셋 중 하나의 노드만 겹치면 된다.
설정에 따라 w와 r을 더 작은 수로 설정해 w+r <=n이 되지 않도록 설정할 수 있다. 성공에 필요한 응답의 수가 더 줄어들지만 n개의 노드로 데이터를 요청하기는 한다. 하지만 w와 r이 작을 수록 오래된 값을 읽을 확룰이 높아진다.
w + r > n 인 경우에도 오래된 값을 반환하는 에지 케이스가 존재한다.
- 느슨한 정족수 loose quorum를 사용하는 경우 w개의 쓰기가 r개의 읽기와 다른 노드에서 발생할 수 있음으로 w노드와 r노드가 겹치는 것을 보장하지 않음
- 두 개의 쓰기가 동시에 발생하면 충돌이 발생함. 이는 쓰기 충돌을 어떻게 다루냐에 대한 문제임
- 쓰기와 읽기가 동시에 발생하면 최신의 값을 읽는다는 보장이 없음 (복제 중 읽기)
- 쓰기가 일부만 성공한 경우 일단 써진 쓰기는 롤백하지 않기 때문에 오래된 값이 읽을 가능성이 있음
- 새 값을 전달하는 노드가 고장나는 경우 w 값이 낮아져 정족수가 깨질 수 있다.
- 모든 과정이 정상 동작해도 시점 문제로 에지 케이스 발생 가능 –> 선형성과 정족수 문제
그 외에도 앞서 이야기한 문제점(복제 지연 등)들이 발생하는 경우 정족수가 순간적으로 지켜지지 않을 수 있다. 이 경우 트랜잭션이나 합의와 같은 별도의 방법이 필요하다.
최신성 모니터링
리더 없는 복제 시스템에서는 쓰기가 적용된 순서를 고정할 수 없어서 모니터링이 어렵다. 더욱이 데이터베이스가 읽기 복구만 사용한다면 자주 읽히지 않는 값이 얼마나 오래된 것인지에 대한 제한이 없어 오래된 복제 서버에서 반환된 값은 아주 오래된 값일 수 있다.
리더 없는 복제에서는 복제 노드의 오래된 정도를 측정하고 그 비율을 매기기도 한다.