마지막으로 남은 질문입니다. 같은 값을 여러 서버에 두어야 할까요. 저장소라면 당연히 그렇습니다. 캐시에서는 답이 다릅니다.
사본은 용량을 먹는다
클러스터 전체 메모리는 정해져 있습니다. 사본을 두 벌 두면 같은 메모리에 담을 수 있는 서로 다른 키가 절반이 됩니다. 담는 키가 줄면 평소 적중률이 내려갑니다.
| 상황 | 사본 한 벌 | 사본 두 벌 |
|---|---|---|
| 평소 | 담는 키가 많다. 적중률이 높다 | 담는 키가 절반. 적중률이 낮다 |
| 장애 | 그 서버 몫이 미스가 된다 | 사본이 받아 미스가 없다 |
평소를 위해 쓰는 캐시라면 사본은 손해일 수 있습니다. 캐시는 항상 켜져 있고 장애는 드물게 옵니다. 드문 순간을 위해 늘 절반을 쓰는 셈입니다.
이 요구사항에서는 두지 않는다
앞 단계에서 계산한 값을 그대로 씁니다. 링과 가상 노드를 쓰면 서버 한 대가 빠질 때 이동하는 키가 약 1퍼센트이고, 미스는 평소의 1.2배입니다.
사본 없이 한 대가 빠질 때: 미스가 2.5만에서 3만으로
적중률 95퍼센트 유지 요구사항 안에 들어온다
요구사항이 이미 충족되므로 사본을 두지 않습니다. 대신 미스가 몰릴 때 원본을 보호하는 장치에 그 여력을 씁니다. 같은 키에 대한 동시 미스를 하나로 합쳐 원본에 한 번만 묻는 방식이 대표적입니다.
사본을 둔다면 어디에 두나
캐시가 아니라 저장소이거나, 장애 시 미스도 허용되지 않는 경우라면 사본을 둡니다. 링에서는 시계 방향으로 다음 지점들에 둡니다.
여기에 함정이 하나 있습니다. 가상 노드를 쓰면 다음 지점이 같은 물리 서버일 수 있습니다.
다음 지점을 그대로 사본 위치로 쓰면
같은 서버에 원본과 사본이 함께 놓인다
그 서버가 죽으면 둘 다 사라진다
그래서 사본 위치를 고를 때 이미 고른 물리 서버는 건너뜁니다. 지점이 아니라 서버 단위로 세어야 합니다. 이 실수는 평소에 아무 증상이 없고 장애가 났을 때만 드러납니다.
무엇을 안 하기로 했는지 말한다
이 아키타입의 답은 대부분 덜 하는 쪽이었습니다.
| 후보 | 결정 |
|---|---|
| 담당을 중앙에 물어보기 | 하지 않는다. 예산이 왕복을 허용하지 않는다 |
| 나머지 연산 | 하지 않는다. 구성 변경이 잦다 |
| 사본 두기 | 하지 않는다. 요구사항이 이미 충족된다 |
| 뜨거운 키 전용 서버 | 하지 않는다. 로컬 캐시로 충분하다 |
요구사항이 이미 충족되면 더 하지 않는 것이 설계입니다. 하지 않기로 한 것과 그 근거를 말할 수 있으면, 같은 문제를 다른 제약에서 다시 풀 수도 있습니다.