Foundry
키-값 저장소 설계
심화
핵심

정족수로 조절하기

몇 개의 응답을 기다릴지가 손잡이다

사본이 셋이라고 정했습니다. 그러면 새 질문이 생깁니다. 쓸 때 몇 개가 성공하면 성공이라고 할까요. 읽을 때 몇 개에서 받아야 할까요.

이 두 숫자가 일관성과 가용성과 지연을 함께 조절하는 손잡이입니다.

숫자 두 개

사본 수를 셋이라 하고, 쓰기에 필요한 성공 수와 읽기에 필요한 응답 수를 각각 정합니다.

쓰기 성공 수 + 읽기 응답 수 > 사본 수

이 관계가 성립하면 읽을 때 받는 응답 중 최소 하나는 최신 쓰기를 받은 사본입니다. 셋 중 둘에 썼고 셋 중 둘에서 읽으면, 둘과 둘은 겹치지 않을 수 없습니다.

조합성질
쓰기 1, 읽기 1가장 빠르다. 최신 값을 만난다는 보장이 없다
쓰기 2, 읽기 2최신 값을 만난다. 한 대가 죽어도 동작한다
쓰기 3, 읽기 1읽기가 매우 빠르다. 한 대만 죽어도 쓰기가 실패한다

가용성 요구가 조합을 좁힌다

요구사항이 분단 중에도 쓰기를 받으라고 했습니다. 쓰기에 셋을 요구하면 한 대만 죽어도 쓰기가 실패하므로 그 요구를 어깁니다.

그래서 쓰기는 둘, 읽기는 둘로 둡니다. 한 대가 죽어도 양쪽 모두 동작하고 최신 값도 만납니다.

기다리는 수가 꼬리 지연을 정한다

사본 셋에 보내고 둘의 응답만 기다리면 가장 느린 응답을 기다리지 않아도 된다 사본 셋에 동시에 보낸다. 각자 응답 시간이 다르다 사본 1 2ms 사본 2 3ms 사본 3 40ms. 마침 바쁘다 둘만 기다리면 3ms 에 끝난다 셋을 다 기다리면 40ms. 가장 느린 하나가 지연을 정한다 둘을 기다리면 느린 하나를 버릴 수 있다 기다리는 수를 줄이는 것이 꼬리 지연을 줄이는 방법이다 대신 쓰기 둘, 읽기 둘이어야 최신 값을 만난다

셋에 모두 보내고 둘의 응답만 기다립니다. 그러면 마침 바쁜 사본 하나를 버릴 수 있습니다.

이것이 정족수의 덜 알려진 이득입니다. 규모가 커지면 어느 순간에도 몇 대는 느립니다. 셋을 다 기다리면 가장 느린 하나가 매 요청의 지연을 정합니다. 읽기 10ms 요구를 지키는 데 이 성질이 결정적입니다.

그래도 최신을 보장하지 못하는 경우

쓰기 둘, 읽기 둘이어도 어긋나는 상황이 남습니다.

상황무슨 일이 생기나
쓰기가 둘에 실패하고 하나만 성공실패로 응답했는데 그 하나에는 값이 남는다
두 쓰기가 동시에 다른 사본에 도달사본마다 순서가 다르게 보인다
분단 중 양쪽이 각자 둘을 채움겹치지 않는 두 정족수가 생긴다

정족수는 최신 값을 만날 확률을 높이는 장치이고, 순서를 정해 주지는 않습니다. 순서를 정하려면 리더가 필요한데 이 설계는 리더를 포기했습니다. 그래서 다음 단계에서 값이 갈렸을 때 무엇을 최신으로 볼지 정합니다.

응용마다 다르게 줄 수 있다

이 두 숫자는 요청마다 바꿀 수 있습니다. 세션 정보는 쓰기 하나로 빠르게 쓰고, 사용자 설정은 쓰기 둘로 안전하게 쓰는 식입니다.

한 저장소 안에서 데이터마다 다른 값을 주는 것이 이 방식의 큰 장점입니다. 다만 응용이 그 뜻을 알아야 하고, 모르고 쓰면 어떤 데이터는 이유 없이 낡은 값을 보게 됩니다.

면접에서 이렇게 나옵니다

Q.정족수를 어떻게 정하시겠습니까

쓰기 성공 수와 읽기 응답 수의 합이 사본 수보다 크게 둡니다. 사본이 셋이면 쓰기 둘, 읽기 둘입니다.

쓰기 성공 수 + 읽기 응답 수 > 사본 수
2 + 2 > 3

이 관계가 성립하면 읽을 때 받는 응답 중 최소 하나는 최신 쓰기를 받은 사본입니다. 셋 중 둘과 셋 중 둘은 겹치지 않을 수 없습니다.

조합성질
쓰기 1, 읽기 1가장 빠르다. 최신 보장이 없다
쓰기 2, 읽기 2최신을 만난다. 한 대가 죽어도 동작한다
쓰기 3, 읽기 1읽기가 빠르다. 한 대만 죽어도 쓰기 실패

흔한 실수: 쓰기에 사본 전체를 요구하는 것. 일관성은 가장 강해지지만 한 대만 죽어도 쓰기가 멈춥니다. 가용성을 고른 설계에서 이 조합은 요구사항을 정면으로 어깁니다.

Q.읽기 10ms 를 정족수로 어떻게 돕나요

셋에 모두 보내고 둘의 응답만 기다립니다. 가장 느린 하나를 버릴 수 있습니다.

사본 1: 2ms
사본 2: 3ms
사본 3: 40ms. 마침 바쁘다
둘만 기다리면 3ms 에 끝난다

규모가 커지면 어느 순간에도 몇 대는 느립니다. 셋을 다 기다리면 가장 느린 하나가 매 요청의 지연을 정합니다. 상위 1퍼센트 지연을 지키려면 이 차이가 결정적입니다.

흔한 실수: 정족수를 일관성 장치로만 설명하는 것. 꼬리 지연을 줄이는 효과가 실무에서는 더 크게 체감됩니다. 기다리는 수를 줄이는 것이 느린 사본을 우회하는 방법이라는 점을 함께 말해야 합니다.

Q.쓰기 둘, 읽기 둘이면 항상 최신 값을 보나요

아닙니다. 정족수는 확률을 높이는 장치이고 순서를 정해 주지는 않습니다.

상황무슨 일이 생기나
쓰기가 하나만 성공하고 실패로 응답실패라고 알렸는데 그 하나에는 값이 남는다
두 쓰기가 동시에 다른 사본에 도달사본마다 순서가 다르게 보인다
분단 중 양쪽이 각자 둘을 채움겹치지 않는 두 정족수가 생긴다

순서를 정하려면 모든 쓰기가 한 곳을 지나야 하는데, 이 설계는 가용성을 위해 그 한 곳을 포기했습니다.

그래서 값이 갈렸을 때 무엇을 최신으로 볼지 따로 정해야 합니다.

흔한 실수: 정족수가 강한 일관성을 준다고 답하는 것. 겹침이 보장하는 것은 최신 쓰기를 본 사본이 응답에 포함된다는 것뿐이고, 여러 값 중 어느 것이 최신인지 판단하는 일은 남아 있습니다.

Q.데이터마다 정족수를 다르게 줄 수 있나요

네. 요청마다 바꿀 수 있고, 그것이 이 방식의 큰 장점입니다.

세션 정보: 쓰기 하나로 빠르게
사용자 설정: 쓰기 둘로 안전하게

한 저장소 안에서 데이터의 성격에 맞춰 조절할 수 있습니다. 전체를 안전한 쪽으로 맞추면 빠를 수 있는 것까지 느려지고, 전체를 빠른 쪽으로 맞추면 중요한 데이터가 위험해집니다.

다만 응용이 그 뜻을 알아야 합니다. 모르고 쓰면 어떤 데이터는 이유 없이 낡은 값을 보게 되고, 원인을 저장소 문제로 오해합니다.

흔한 실수: 기본값을 빠른 쪽으로 두고 문서에 적지 않는 것. 저장소를 쓰는 사람은 기본값이 안전한 쪽이라고 가정합니다. 기본값이 무엇을 보장하지 않는지를 먼저 알려야 합니다.

먼저 스스로 답해보고 아래 답변과 견줘보세요. 막히는 부분은 문제로 확인할 수 있어요.

읽었으면 문제로 확인해보세요

키-값 저장소 설계 문제를 풀면 틀린 문제가 자동으로 노트에 쌓입니다. 가입 없이 5문제를 먼저 풀어볼 수도 있어요.