Foundry
URL 단축기 설계
심화
핵심

읽기 경로 다루기

작은 캐시가 대부분을 덮는다

조회 초당 1만 를 모두 받기로 했습니다. 누적 300억 개 중에서 키 하나를 찾는 일을 50ms 안에 끝내야 합니다.

조회는 소수의 링크에 몰린다

상위 소수의 링크가 조회의 대부분을 차지하므로 작은 캐시가 대부분을 덮는다 링크 개수 기준 보라색이 인기 링크. 전체의 1퍼센트도 안 된다 조회 수 기준 같은 링크들이 조회의 대부분을 차지한다 그래서 작은 캐시로도 대부분의 조회를 덮는다 300억 개를 다 담을 필요가 없다

링크는 공유되면서 조회가 폭발하고 대부분은 거의 열리지 않습니다. 며칠 전에 만든 링크는 사실상 조회되지 않습니다.

그래서 누적 300억 개 을 모두 빠르게 찾을 필요가 없습니다. 인기 있는 소수를 메모리에 두면 대부분의 조회가 거기서 끝납니다.

캐시에 담는 양덮는 조회
인기 상위 소수대부분
전체필요 없다. 담을 수도 없다

이 편중이 이 설계를 값싸게 만드는 성질입니다. 편중이 없다면 누적 300억 개 을 모두 빠르게 찾아야 하고 훨씬 비싼 설계가 됩니다.

캐시에 무엇을 어떻게 담나

키를 열쇠로, 목적지 주소를 값으로 담습니다. 값이 짧아 메모리 효율이 좋습니다.

담는 규칙은 단순합니다. 조회했는데 없으면 저장소에서 찾아 캐시에 넣습니다. 오래 안 쓰인 것부터 밀어냅니다.

만료를 짧게 둘 이유가 없습니다. 키와 목적지의 대응은 거의 바뀌지 않기 때문입니다. 다만 링크가 만료되거나 삭제될 때 캐시에서 지워야 하고, 그 처리를 빼먹으면 만료된 링크가 계속 동작합니다.

없는 키 조회가 문제가 된다

없는 키로 요청이 오면 캐시에 없고 저장소에도 없습니다. 그 요청은 매번 저장소까지 갑니다.

정상 사용자도 이런 요청을 만듭니다. 오타나 잘린 링크가 그렇습니다. 그런데 키를 훑어 보는 시도가 있으면 그 요청이 대량으로 들어옵니다.

대응내용
없다는 사실도 캐시에 담는다같은 키의 반복 요청을 막는다
요청량을 제한한다훑어 보기를 늦춘다

없다는 사실을 담을 때는 짧게 둡니다. 방금 만든 키를 없다고 기억하면 그 링크가 잠깐 동작하지 않습니다.

저장소는 무엇으로 고르나

조회가 키 하나로 값 하나를 가져오는 형태뿐입니다. 범위 조회도, 여러 키를 묶는 트랜잭션도 필요 없습니다.

키-값 저장소가 정확히 맞는 모양입니다. 6장의 설계가 그것이고, 이 서비스는 그 저장소의 전형적인 사용자입니다.

캐시가 비면 무슨 일이 생기나

캐시 서버를 재시작하거나 늘리면 캐시가 비고, 그동안 모든 조회가 저장소로 갑니다. 초당 1만이 그대로 저장소를 때립니다.

앞의 아키타입에서 본 문제와 같습니다. 한 번에 비우지 않고 조금씩 채우는 방법으로 다룹니다. 캐시 서버를 늘릴 때 담당을 조금씩 옮기는 것이 안정 해시 설계에서 다룬 그 절차입니다.

면접에서 이렇게 나옵니다

Q.누적 300억 개 중에서 키를 50ms 안에 어떻게 찾나요

인기 있는 소수를 메모리에 담습니다. 전체를 빠르게 찾을 필요가 없습니다.

링크는 공유되면서 조회가 폭발하고 대부분은 거의 열리지 않습니다. 그래서 상위 소수를 캐시에 두면 대부분의 조회가 거기서 끝납니다.

캐시에 담는 양덮는 조회
인기 상위 소수대부분
전체필요 없고 담을 수도 없다

이 편중이 설계를 값싸게 만드는 성질입니다. 편중이 없다면 훨씬 비싼 설계가 됩니다.

흔한 실수: 캐시 크기를 전체 데이터 기준으로 계산하는 것. 필요한 크기는 조회가 몰리는 양으로 정하고, 그것은 실측으로 알아냅니다.

Q.없는 키로 오는 조회는 어떻게 다루나요

없다는 사실도 캐시에 짧게 담습니다.

없는 키는 캐시에도 저장소에도 없으므로 매번 저장소까지 갑니다. 오타나 잘린 링크로 정상 사용자도 이런 요청을 만들고, 키를 훑어 보는 시도가 있으면 대량으로 들어옵니다.

대응내용
없다는 사실을 캐시에 담는다같은 키의 반복을 막는다
요청량을 제한한다훑어 보기를 늦춘다

짧게 담는 것이 중요합니다. 방금 만든 키를 없다고 기억하면 그 링크가 잠깐 동작하지 않습니다.

흔한 실수: 없다는 사실을 일반 항목과 같은 시간으로 담는 것. 생성 직후 조회는 흔한 흐름이고, 그때 없다는 기억이 오래 남으면 사용자가 만든 링크가 바로 깨진 것으로 보입니다.

Q.저장소를 무엇으로 고르시겠습니까

키-값 저장소입니다. 조회 모양이 정확히 그것입니다.

키 하나로 값 하나를 가져오는 형태뿐이고, 범위 조회도 여러 키를 묶는 트랜잭션도 필요 없습니다. 요구사항에서 이미 그것들을 범위 밖으로 뺐습니다.

조회: 키로 목적지 하나
쓰기: 키와 목적지 한 쌍

이 단순함이 저장소 선택을 쉽게 만듭니다. 그리고 {REQ['total']} 을 나눠 담아야 하므로 나누는 기준도 키 하나로 분명합니다.

흔한 실수: 관계형 저장소를 기본값으로 고르는 것. 쓸 수는 있지만 이 조회 모양에 필요 없는 것을 많이 지불합니다. 반대로 통계와 관리 기능은 관계형이 편하므로 그쪽만 따로 두는 것도 방법입니다.

Q.캐시가 비면 무슨 일이 생기나요

초당 1만 조회가 그대로 저장소를 때립니다.

캐시 서버를 재시작하거나 늘리면 캐시가 비고, 그동안 모든 조회가 저장소로 갑니다. 저장소는 평소 미스만 받도록 맞춰져 있으므로 그 부하를 감당하지 못합니다.

그래서 한 번에 비우지 않고 조금씩 채웁니다.

캐시 서버를 늘릴 때 담당을 조금씩 옮긴다
미스가 시간에 걸쳐 흩어진다

안정 해시 설계에서 다룬 절차와 같습니다.

흔한 실수: 캐시를 비우는 작업을 운영 작업으로만 보는 것. 이 서비스에서 캐시는 저장소를 지키는 장치라, 비우는 순간이 곧 저장소가 가장 위험한 순간입니다.

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

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

URL 단축기 설계 문제를 풀면 틀린 문제가 자동으로 노트에 쌓입니다. 가입 없이 5문제를 먼저 풀어볼 수도 있어요.