이 글은 Martin Kleppmann의 데이터 중심 애플리케이션 설계를 읽고 기억하고자 적는 게시글입니다.
5. 복제
복제는 네트워크로 연결된 여러 장비에 동일한 데이터의 복사본을 유지하는 것입니다. 그렇게 되면 동일한 데이터를 중복으로 저장하게 되고 저장 공간의 사용량이 늘어나게 되는데 왜 복제를 하는걸까요?
이유는 다음과 같습니다.
1. 지리적으로 사용자와 가깝게 데이터를 유지해서 지연 시간을 줄 일 수 있습니다.
2. 시스템의 일부에 장애가 발생해도 지속적으로 동작 할 수 있게 해 가용성을 늘립니다.
3. 읽기 질의를 제공하는 장비의 수를 확장해 읽기 처리량을 늘립니다.
이러한 장점을 위해 복제를 수행합니다. 그런데 아예 변경되지 않는 불변 데이터만을 저장하면 매우 편합니다. 왜냐하면 1번 저장 한 후에 더 이상 데이터가 변경되지 않는다면 그냥 스토리지에 넣고만 있으면 되니까요.
하지만 문제는 삭제 및 갱신이 가능 한 데이터의 복제가 어렵다는 점 입니다.
이전에는 노드 간 변경을 복제 하기 위한 세 가지 인기있는 알고리즘 중 단일 리더, 다중 리더를 알아보았습니다.
이번 포스트에서는 리더 없는 복제에 대해서 알아보겠습니다.
리더 없는 복제
리더 팔로워 기반의 복제 방식은 사용자가 쓰기 요청한 값을 리더 노드가 받아서 리더 노드에 데이터를 입력 한 다음 팔로워 노드들에게 그 복제 내역을 전달하는 방식으로 복제를 진행했습니다.
하지만 리더 없는 복제는 사용자의 데이터를 모든 노드가 받게 됩니다. 모든 노드는 받은 데이터를 입력하게 됩니다. 이런 방식의 대표적인 예로 Dynamo DB가 있습니다.
리더 없는 복제에서는 코디네이터 노드가 쓰기 요청을 보낼 수 있다고 하는데, 이 부분은 더 알아보겠습니다.
1. 데이터 입력 중 노드가 다운 되었을 때
어떻게 보면 정말 안전해보이지만 ( 적어도 1개의 노드에는 데이터가 있으므로 ) 중간에 노드가 죽었을 때 리더의 개념이 없는 노드들은 어떻게 동작할까요?
첫 번째로 중요한 특징은 데이터 입력 과정에서의 노드 다운은 고려하지 않는다입니다.
A, B, C 노드 중 C 노드가 다운되어 데이터를 입력받지 못하더라도 그대로 완료합니다. 이 때 최소 몇 개의 노드가 입력이 완료 되었는지에 대한 파라미터가 별도로 있는 듯 합니다. ( 최소한의 안전성을 보장하기 위함 )
2. 복구
복구 방식에는 크게 2가지가 있습니다.
1) 읽기 복구
클라이언트가 여러 노드에서 병렬로 데이터를 읽어 올 때 불러 온 데이터를 식별하는 버전 값을 이용하여 최신 버전을 특정하고, 오래 된 버전이 있으면 업데이트 시킵니다.
- 자주 읽는 값의 경우에는 최신 버전으로 갱신됨을 보장 할 수 있습니다.
- 연산또한 데이터를 읽을 때 실행되며, 선택적으로 데이터를 갱신하기 때문에 부하가 크지 않습니다.
- 문제는 자주 읽지 않는 값의 경우에는 업데이트가 되지 않을 수 있습니다.
2) 안티 엔트로피 처리
백그라운드 프로세스를 통해 데이터의 차이를 찾아서 누락 된 데이터를 다른 노드에게서 복사해오는 방식입니다.
- 어느정도의 기간 차이로 가장 최신 버전을 상시 유지 할 수 있습니다.
- 연산이 많고, 비용이 많이 소요되어서 부하카 큽니다.
3. 읽기와 쓰기를 안정적으로 수행하기 위한 조건
위에서는 3개의 노드 중 적어도 2개의 노드에 쓰기가 완료되어야 확정했고, 읽어 올 때는 모든 노드에서 데이터를 읽어왔습니다. 이렇듯 리더 없는 복제방식 에서는 N개의 노드 중 적어도 W개의 노드에는 써야하고 R개의 노드를 읽어야 한다는 파라미터가 필요합니다.
이 값들을 정족수라고 부르며 무조건 최신의 데이터를 읽어 올 수 있다는 보장 된 공식은 다음과 같습니다.
\[W + R > N\]위 공식이 맞아 떨어지면 적어도 한 개의 노드는 최신의 데이터를 가지고 있기 때문에 읽기 복구를 수행 할 수 있습니다.
보통 Dynamo 스타일의 데이터베이스에서는 다음의 기본값으로 설정한다고 합니다.
\[W = R = ROUND((N+1)/2)\]필요한 W와 R개의 노드보다 사용가능 한 노드가 적다면 쓰기나 읽기 과정 중 에러를 반환한다고 합니다.
4. 정족수 일관성의 한계
기본적으로 위에서 이야기 한 정족수의 비중을 맞추는 것이 안전하지만, 오래 된 값을 읽어도 된다면 W와 R의 수를 줄이는 것 또한 가능하다고 합니다. 이유는 노드가 적을 경우 많은 노드가 응답하지 못한다면, 쓰기 읽기 처리가 원활하게 진행되지 않을 수 있기 때문입니다.
\[W+R <= N\]도 가능하기는 합니다.
뿐만아니라 쓰기와 읽기가 동시에 동작하는 경우에도 일부 복제 서버에만 변경 사항이 저장되어 있을 수 있고, 특정 노드가 살아있지만 입력에 실패 했을 경우 원치 않은 결과를 얻을 수도 있습니다.
사실 리더 없는 복제를 채택한 데이터베이스를 사용 할 때 좋은 Use Case가 오래 된 데이터를 읽을 수 있다는 전제가 있는 데이터 적재 입니다. 물론 그런 일이 최소한으로 일어나는게 좋겠지만, 적어도 W개 이상의 데이터는 최근 데이터를 가지고있고, 누락이 없기에는 이만한 데이터베이스가 없습니다.
5. 느슨한 정족수
지금까지 공부 한 내용 중 리더 없는 복제의 크리티컬한 문제 중 하나는 사용가능 한 노드의 수가 쓰기 혹은 읽기 노드 갯수보다 적으면 에러를 출력한다 였습니다.
이 경우 여러 이유로 사용가능 한 노드의 수가 줄어들었을 때 입력되는 모든 쓰기 요청과 읽기 요청은 동작하지 않게 되어 버립니다.
이 때 우리는 느슨한 정족수라는 옵션을 사용해서 현재 사용중인 노드가 쓰기 노드 갯수보다 작다면 연결할 수 있는 다른 노드에라도 적는 동작이 가능합니다. 여기에는 N에 포함되지 않는 서버도 포함 될 수 있습니다.
이후 네트워크 장애 상황등이 해결되면 일시적으로 받은 데이터를 홈노드(N에 포함되는)로 전송합니다. 이 과정을 암시된 핸드오프(번역뭐죠?)라고 합니다…??