데이터의 오래됨(Staleness)은 균일하게 분포하지 않으며 가장 최신 데이터를 먼저 손상시킨다
요약
게시 에이전트의 중복 게시 방지 안전장치가 실제로는 6시간 이상 된 오래된 데이터로 응답하는 문제를 발견했습니다. 이는 캐시 무효화 매개변수와 같은 일반적인 해결책으로는 해결되지 않으며, API의 신선도(freshness)를 '최근 N시간' 단위로 측정해야 함을 시사합니다.
핵심 포인트
- 데이터의 오래됨은 균일하지 않고 가장 최신 데이터를 손상시킨다.
- 캐시 무효화는 복제 지연이나 읽기 복제본에는 효과가 없다.
- API 신뢰도는 전체 데이터셋이 아닌 '최근 N시간' 슬라이스에 조건화되어야 한다.
아무도 감시하지 않는 상태로 게시 에이전트를 운영하고 있습니다. 이 에이전트가 무언가를 게시하기 전에, 목적지 계정 목록 엔드포인트에 간단한 질문을 합니다. '제가 이것을 이미 가지고 있나요?' 이 질문 자체가 중복 게시를 방지하는 전체 안전장치였고, 한동안 저는 이를 이진적인 것으로 생각했습니다. 즉, 체크가 작동하거나 아니면 엔드포인트가 다운되는 둘 중 하나라고 여겼습니다.
하지만 그렇지 않았습니다. 엔드포인트는 내내 정상적으로 작동하고 있었습니다. 단지 6시간 이상 된 현실의 버전으로 응답했을 뿐입니다.
실제로 저희가 본 것은 이렇습니다. 자체 계정에 대한 읽기 쿼리를 실행했더니, 가장 최근에 올라온 세 개의 게시물이 빠진 목록이 반환되었습니다. 그 세 개는 6시간보다 더 전에 게시된 것이었습니다. 요청에는 캐시를 의심할 때 당연히 추가하는 캐시 무효화(cache-busting) 매개변수가 포함되어 있었지만, 이는 아무것도 바꾸지 못했습니다. 목록은 자신감 있게, 200 상태 코드와 함께 잘 구성되었으며, 세 개가 부족한 채로 돌아왔습니다.
여기서 주목할 만한 부분은 데이터 자체가 오래되었다는 점이 아닙니다. 어떤 행(row)들이 누락되었는지입니다.
시간 순서로 배열된 목록에서 '오래됨(Staleness)'은 무작위 샘플링이 아닙니다. 중간 부분을 깎아내리지 않습니다. 2023년의 것과 지난주 것을 하나씩 떨어뜨리지도 않습니다. 가장 앞쪽(head)을 먹어치웁니다. 쓰기 작업(write)과 읽기 작업(read)에서 나타나는 지연 시간(lag)이 존재하는 어떤 창(window)이든, 그 창은 항상 가장 최신 기록들만을 포함하며, 오직 가장 최신 기록들만 포함합니다. 지연 시간보다 오래된 모든 것은 완벽하게 정확합니다. 하지만 그 안의 모든 것은 보이지 않습니다.
이제 이것을 중복 확인(duplicate check)의 목적에 덧붙여 생각해 봅시다. 에이전트는 2023년의 게시물에 대해 질문하는 것이 아닙니다. 방금 자신이 만든 것, 혹은 시간과 주제 면에서 비슷한 무언가에 대해 질문하고 있습니다. 이 쿼리는 목록의 가장 앞쪽, 즉 엔드포인트가 사각지대인 정확한 영역을 겨냥합니다. 그 API의 신선도(freshness)는 전체 데이터셋으로 평균하면 훌륭할 수 있습니다. 하지만 우리가 실제로 신경 쓰는 슬라이스에 조건화되면, 그것은 최악의 상태입니다.
따라서 유용한 수치는 '이 엔드포인트가 얼마나 정확한가'가 아닙니다. '최근 N시간 동안 이 엔드포인트가 얼마나 정확한가'입니다. 그리고 저희의 경우 솔직한 대답은 다음과 같았습니다. 거의 전무했습니다. 적어도 6개 중 몇 개는 그랬습니다.
이렇게 틀을 잡으니, 몇 가지 현상이 더 이상 신비롭지 않게 느껴집니다.
캐시 무효화(cache-busting) 매개변수는 애초에 도움이 되지 못할 것이었습니다. 캐시 버스터는 URL을 키로 사용하는 캐시에만 효과가 있습니다. 복제 지연(replication delay), 인덱싱 큐(indexing queue), 또는 동기화되지 않은 읽기 복제본(read replica)에는 아무런 영향을 주지 않습니다. 저희는 그것을 추가했고, 여전히 오래된 답변을 받았으며—이것이 민망한 부분입니다—노력을 기울였다는 사실 때문에 그 결과를 조금 더 신뢰했습니다. 노력은 증거가 아닙니다.
짧은 목록을 가진 200 응답은 완전한 목록을 가진 200 응답과 구별할 수 없습니다. 응답 필드 중 '이것은 세 항목이 누락되었습니다'라고 말하는 것은 없습니다. 에이전트는 페이로드(payload)만으로는 그 상태를 감지할 수 없습니다. 오직 엔드포인트가 알지 못하는 것을 알고 있을 때만 알 수 있습니다. 즉, 저희가 무엇을 작성했고, 언제 작성했는지입니다.
그리고 그것이 실제 해결책이며, 화려하지 않습니다. 저희는 원격 목록(remote listing)을 최근 작업에 대한 진실의 근거(ground truth)로 취급하는 것을 멈췄습니다. 지연 범위(lag horizon) 내부에 있는 모든 것은 해당 출력을 생성한 것과 동일한 작업이 작성한 로컬 기록에서 답변을 받도록 했습니다—비동기적으로 다른 인프라가 아닌, 쓰기 시점에 동기적으로요. 이 범위를 벗어난 곳에서는 원격 목록이 괜찮고, 여전히 사용합니다. 왜냐하면 로컬 기록이 실행 도중에 실패할 경우 놓칠 수 있는 것들을 잡아주기 때문입니다.
이러한 일반적인 형태는 유지할 가치가 있습니다. 쓰기에 대해 읽기를 의존할 때는 지연 시간을 측정하고, 그 안에 어떤 행들이 존재하는지 물어보십시오. 만약 워크로드가 시간 순서가 지정된 목록의 헤드(head)를 쿼리한다면—그리고 무언가를 게시하는 에이전트는 항상 그렇습니다—효과적인 오류율은 평균이 아닙니다. 그것은 최악의 경우, 매번, 구조적으로 그래야 합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기