Sun Mar 29 2026
...
FastComments가 우주에 준비되었습니다!
! 이 기사에는 기술 전문 용어가 포함되어 있습니다.
새로운 소식
각 FastComments point-of-presence는 이제 로컬로 쓰기를 처리하고 이를 비동기적으로 모든 다른 노드에 복제합니다. 이는 이전 시스템보다 더 높은 내구성을 제공하며, 일부 지역의 사용자에게는 조정 도구를 더 빠르게 만들어 줍니다. 다소의 거래가 필요합니다.
"우주에 준비되었습니다"는 다소 낙관적이지만, 우리의 생각은 FastComments를 다양한 행성에 배포할 수 있다는 것입니다. 결국 시스템은 동기화될 것입니다. 그러나 명왕성에 있는 사용자는 변화가 다가오는 청구서 페이지에 반영되기까지 약 하루를 기다려야 할 것입니다. 현재로서는 지역당 하나의 마스터만이 청구 정보를 집계할 수 있습니다.
역사적인 배경, 변화의 이유
FastComments가 처음 출시되었을 때 우리는 매우 일반적인 아키텍처를 가지고 있었습니다. 프록시 레이어, 앱 레이어, 데이터베이스, 몇 개의 복제본이 있었고, 나중에는 추가 중복성을 위해 지역과 클라우드 공급자에 걸쳐 복제를 이루었습니다.
결국 우리는 데이터베이스 복제본을 대부분의 사용자들이 있는 모든 존으로 이동시키고, 그곳에 앱을 배포했으며, 요청을 가장 가까운 앱 노드로 라우팅하기 위해 자체 DNS 및 프록시 시스템을 만들었습니다(자세한 사항은 나중의 블로그 게시물에서 설명할 예정입니다). 이렇게 하면 읽기가 빨라지지만, 쓰기는 느려집니다. 이제는 백엔드에 대해 한 번의 HTTP 왕복을 기다리는 대신, 가까운 노드에 대한 HTTP 왕복을 기다리게 되고, 그 노드는 다시 주요 노드에 여러 번의 데이터베이스 쓰기를 수행할 수 있습니다. 좋지 않습니다!
그래서 이를 해결하기 위해 우리는 응용 프로그램의 많은 영역을 재구성하여 함수 인수에서 readPreference를 수용하도록 했습니다. 호출자는 자신의 읽기가 얼마나 오래된 상태가 되어도 괜찮은지를 결정할 수 있으며, 이에 덧붙여 더 많은 쓰기 작업(예: 중재자 행동에 대한 중재 통계 쓰기)을 fire-and-forget 방식으로 구현했습니다. 이상적이지는 않지만, 상황을 크게 개선했습니다.
MongoDB를 전 세계적으로 운영하면서 마주친 한 가지 문제는 네트워크 분리입니다. 충분한 수의 노드가 차단되면 각 노드는 읽기를 제공하는 것이 허용되는지 확신할 수 없기 때문에 읽기가 정지합니다. 이를 해결하는 방법은 있지만 극단적인 경우가 복잡해집니다. 이는 이론적인 문제가 아니며, 너무 많은 3AM 페이지를 발생시켰기에 우리는 지쳐버렸습니다. 심지어 MongoDB를 한 번의 선거 불확실성에 대해 1분 차이로 괜찮도록 조정하려고 시도하기도 했습니다. 안타깝게도, 예를 들어 상파울로에서 팔켄슈타인까지의 네트워크는 일부 호스팅 제공업체에서 매우 좋지 않았습니다. 혼잡 제어를 조정하고 기타 방식이 도움이 되었지만, 문제를 해결하지는 못했습니다.
이상적인 해결책은 특정 거래를 수용할 수 있다면, 해당 노드에서 로컬로 쓰기를 수용하고(해당 하드웨어가 뛰어나고 RAID, 등등이 있어 고장 날 가능성이 적음) 사용자에게 데이터를 저장했다고 알리는 것입니다. 그 지점에서 내구성을 위해 핫 복제본으로 두 번째 노드를 갖는 것도 가능합니다.
그래서 우리가 도달한 것이 이것입니다. 오리건, 버지니아, 팔켄슈타인, 상파울로, 싱가포르는 모두 각자의 복제 집합을 가지고 있으며 쓰기를 수용합니다. EU 배포(비록 세 개의 PoP만 있지만)도 동일한 동작을 합니다.
작동 방식
이와 관련된 일부 내용은 이전 섹션에서 다루어졌지만, TL;DR은 CRDT-lite입니다. 우리는 응용 프로그램과 MongoDB 사이에 있는 프록시를 만들었으며(Rust로 만들었습니다, 그럼 당연하죠), 이를 통해 멀티-마스터를 구현했습니다. 프록시는 피어 인식이 가능하고, 체크포인트, 복제, 모니터링 및 초기 동기화를 관리합니다. 이는 MongoDB의 복제 시스템에 대한 멀티 마스터 대체 솔루션으로, 일부 DDL 명령도 포함됩니다.
다른 도구와의 차이점은 oplog을 추적하지 않는다는 것입니다. oplog을 추적하거나 변경 스트림을 사용하는 것은 작동하지 않는데, 이는 쓰기 후 객체의 최종 상태만 보여주므로 충돌을 처리할 수 없습니다. 각 $set, $inc 작업을 캡처하고 그 작업 자체를 복제해야 합니다.
이는 도메인 특화 솔루션입니다. 모든 제품에 적용되지 않을 것입니다. 도메인 주도 설계라고 할 수 있습니다 :). 우리는 처음부터 문서에서 변경하는 필드만 $set하기를 매우 신중하게 수행했으므로, 예를 들어 MongoDB의 replaceOne을 사용한 적이 없습니다. 카운터도 마찬가지입니다. SET VOTES = 5는 절대 하지 않습니다. 대신에 INCREMENT VOTES BY 5라고 작성하여 결국 일관성을 보장합니다. 분산 잠금은 하지 않습니다. 클러스터당 단 하나의 노드만 crons를 실행할 수 있는 플래그가 설정되어 있습니다. 이것이 제한적으로 보일 수 있지만, 우리는 테라바이트(TB) RAM을 장착한 서버를 구매할 수 있으므로, 이 거래를 감수하여 위험과 복잡성을 줄일 수 있습니다.
자신의 쓰기 읽기
API를 사용하는 개발자는 이전과 마찬가지로 자신의 쓰기를 읽을 수 있어야 합니다(댓글을 작성하기 위한 API 호출 후 댓글 목록을 열고 새로운 항목을 확인합니다). 주의점은 지역 간에는 이 작업을 수행할 수 없다는 것입니다. 백엔드가 하나의 지역에서만 실행된다면, 즉 us-west와 같은 경우, 자신의 쓰기를 읽을 수 있어야 합니다. 단, 쓰기와 읽기 사이에 해당 노드가 다운되 고 DNS 캐시가 다음 가까운 노드를 가리키도록 업데이트된 경우를 제외합니다. 이러한 일이 발생하지 않는다면, 자신의 쓰기를 읽는 것은 신뢰할 수 있습니다.
어떤 포인트 오브 프레즌스를 고정할 수도 있습니다. 자세한 정보는 여기에서 확인하세요.
테스트 및 마이그레이션
시스템의 코드 중 절반은 테스트 헌련, 프레임워크 및 테스트입니다. 그럼에도 불구하고 릴리스는 약간 불안정하여, 유럽 연합(EU)은 1시간, 전 세계는 20분가량의 예상보다 긴 다운타임이 있었습니다. 그러나 우리는 이 이정표를 통과한 것에 기쁘며, 여러분의 인내에 감사드립니다!
결론 및 이것이 귀하에게 의미하는 것
FastComments는 이제 그 어느 때보다 빠르고 내구성이 향상되었습니다. 이제 기능 작업으로 돌아갈 수 있습니다 :)
건배!
