본문 바로가기

[뉴스] 클라우드플레어, 1.1.1.1 DNS 캐시 구조 다섯 번 손봐 메모리 100TB 절감 - 항목당 953바이트에서 420바이트로

조회 1 · 댓글 0
¯¯\_(ツ)_/¯작성자2026년 8월 28일

클라우드플레어가 8월 27일 엔지니어링 블로그에 공개 DNS 리졸버 1.1.1.1의 캐시 메모리를 어떻게 줄였는지 상세히 풀어놓았습니다. 1.1.1.1과 Gateway DNS, DNS Firewall 등을 떠받치는 내부 플랫폼 "Big Pineapple"은 항상 2,500억 개가 넘는 DNS 캐시 항목을 들고 있는데, 이 규모에서는 항목 하나에 1바이트만 아껴도 전체 서버군 기준 250GB가 절약됩니다. 캐시 항목의 메모리 배치를 다섯 차례 바꾼 결과 항목당 메모리는 절반 이하로 줄었고, 전체로는 약 100테라바이트의 RAM이 비었다고 합니다. 회사 측은 이를 자사 13세대 서버 130대 분량이라고 설명합니다.

다섯 가지 변경은 전부 Rust 자료구조 수준의 손질입니다. 첫째, 한 번 저장한 뒤 절대 수정하지 않는 응답인데도 Vec과 String을 쓰고 있어 용량(capacity) 필드 8바이트와 여유 힙 공간이 낭비되던 것을 Box<[T]>, Box<str>로 바꿨습니다. 항목당 8개 필드였으니 64바이트가 빠집니다. 둘째, answer, authority, additional 세 섹션을 각각 별도 리스트로 두던 것을 하나의 리스트에 u16 오프셋 두 개로 합쳐 28바이트를 더 줄였습니다. 셋째, 레코드마다 들고 있던 소유자(owner) 도메인이 대부분 질의한 도메인과 같다는 점을 이용해 같으면 비워 두고 조회 시 캐시 키에서 복원하도록 했습니다. CNAME 뒤에 붙는 A 레코드처럼 다를 때만 힙에 전체 이름을 저장합니다.

넷째는 enum 크기 문제입니다. Rust enum은 가장 큰 variant 크기로 고정되는데, 레코드 데이터 enum에서는 NAPTR이 136바이트로 가장 커서 전체가 144바이트였습니다. 트래픽의 80% 이상인 A(4바이트)와 AAAA(16바이트) 레코드가 120바이트 넘게 패딩으로 버려지던 셈이라, 큰 variant를 Box로 힙에 내보내 enum 자체를 24바이트로 줄였습니다. 다만 이렇게 하면 jemalloc의 크기 클래스 반올림 낭비와 힙 여기저기로 데이터가 흩어지는 지역성 저하가 따라옵니다. 그래서 다섯째로, 파싱된 enum 대신 레코드 데이터를 2바이트 길이 접두어가 붙은 원시 바이트(wire format)로 한 덩어리 Box<[u8]>에 이어 붙이는 방식으로 다시 갈아탔습니다. 응답 전체를 wire format으로 저장하면 DNSSEC DO 플래그 유무에 따라 두 벌을 캐시해야 해서 레코드 데이터만 원시 바이트로 두는 절충안을 택한 것입니다.

이 마지막 변경은 속도에도 이득이었습니다. A, AAAA, TXT, DNSSEC 레코드는 필드별 재직렬화 없이 버퍼에서 응답으로 그대로 복사되고, 도메인 이름을 포함해 이름 압축이 필요한 CNAME, NS, MX, SOA만 파싱을 거칩니다. 벤치마크에서 이 단계만으로 조회 지연이 5% 줄었고, 삽입 시 재사용 스크래치 버퍼에 먼저 쓴 뒤 한 번만 할당하는 방식으로 삽입 처리량도 13% 올랐습니다.

최종 수치를 보면 벤치마크 기준 항목당 순 메모리는 953바이트에서 420바이트로 56% 감소, 항목당 할당량은 1.1KB에서 461바이트로 58% 감소했습니다. 캐시 삽입 처리량은 초당 62만 5천 건에서 89만 3천 건으로 43% 늘고, 조회 지연은 828ns에서 670ns로 19% 짧아졌습니다. 실제 운영 환경에서는 2026년 5월 18일부터 7월 6일까지 단계적으로 배포됐고, 인스턴스당 상주 메모리가 p99 기준 9.3GB에서 5.3GB(43% 감소), p90 기준 6.5GB에서 3.8GB(42% 감소)로 내려갔습니다. 캐시 외 프로세스 메모리가 섞여 있어 운영 수치가 벤치마크보다 작게 나온다는 설명도 덧붙였습니다.

클라우드플레어는 확보한 메모리를 메모리 사용량은 그대로 두고 캐시 용량을 키우는 데 재투자해 캐시 적중률을 높이고 상위 서버 질의를 줄일 계획이라고 밝혔습니다. 규모가 다르더라도 "불변 데이터에 Vec 쓰지 않기", "enum은 가장 큰 variant만큼 커진다", "작은 할당 여러 개보다 연속된 한 덩어리" 같은 교훈은 대용량 인메모리 캐시를 다루는 분들이라면 한 번쯤 자기 코드에 대조해 볼 만한 내용입니다.

🔗 https://blog.cloudflare.com/dns-cache-memory-optimization-1111/

로그인 후 답글을 남길 수 있습니다.