1. 최근 대형SNS의 Downtime 사례

    최근 발생한 몇몇 대형 서비스들의 Downtime에 대해 기술적으로 살펴봤다.

    #1. Facebook: 9월 23일 / 2시간 30분 downtime

    5억명이 넘는 사용자를 가지고 있는 페이스북의 경우 성능을 위해 약800대의 메모리캐슁서버(memcached)에 28테라바이트의 소셜 그래프 데이터를 담아 사용자들에게 서비스 한다. 이는 5억명이라는 사용자를 상대하기 위한 페이스북의 가장 중요한 부분이다. (UDP로 통신하는 가장 고성능의 memcached를 자체적으로 만들어 사용하는 것으로 이미 알려져있다.) 메모리캐슁서비스는 원본 데이터를 빠르게 접근하기 위해 메인 메모리에 데이터를 두는 저장소다. 문제는 원본 데이터가 변경이 되면 캐슁도 따라서 갱신을 해줘야하는데 이번 사건은 모든 메모리캐슁서비스가 원본데이터를 다시 확인하고 갱신하는 이른바 cache invalidation과정이 연쇄적으로 일어나면서 마스터DB에 대한 일종의 DDoS공격과 같은 것이 되어버렸다. (마스터DB가 과부하가 걸리면서 접근이 실패한 클라이언트의 재시도에 의해 더 많은 요청이 발생하게 되는 악순환 구조가 생겨난다.) 이는 페이스북 엔지니어의 실수로 cache invalidation 명령을 사용자들이 접근하는 데이터 서버쪽에 오더한 것이 발단이 되었다.

    문제가 중앙서버에 영향을 끼쳐 결국 서비스를 더 이상 못하는 상태가 되어 Like버튼이 달려있는 35만개의 외부사이트가 이를 지켜봤단다. 결국 모든 서비스는 중단되고 다시 하나씩 가동시켜 정상으로 복구가 되었다.

    이번 문제는 사람의 실수가 원인이긴 하지만 느슨하게 연결되어 있는 분산시스템의 복잡도가 높아져 가면서 하나의 작은 실수가 전체 시스템을 흔들어 버릴 정도의 위험을 초래할 수 있다는 교훈을 남겼다. 예전에 MSSQL의 request flooding에 의해 통신장비를 마비시켜서 나라 전체의 네트워크를 마비시켰던 일도 떠올리게 한다. 수백에서 수천대의 서버가 하나의 상태로 동기화 하는데 걸리는 절대적인 지연시간(propagation delay)이 있기 때문에 혹 잘못된 정보 때문에 한쪽 부분이 무너지게 되면 이로 인해 생겨나는 영향력을 더 이상 제어할 수 없게 되는 순간들이 발생한다.

    #2. Foursquare: 10월 4일 / 11시간 downtime

    약 3백만명의 사용자를 가지고 있는 4sq의 경우 사용자가 check-in하는 모든 데이터는 사용자id를 key로 해 내부 db서버중 하나에 분배되어 저장된다. 이를 sharding이라고 하는데 모든 데이터는 여러 서버에 골고루 분배 된다. 이는 consistent hashing을 이용하기 때문이다.

    이번에 발생한 문제는 DB서버중 하나에 이상하게 많은 양의 check-in이 쏠리면서 시작되었다. 그 시각이 오전 11시. 12시 반까지 이런 저런 시도를 했으나 실패하였고 이 이후에 새로운 서버로 교체하는 작업을 했다고 한다. 새로 교체한 서버에 이전 데이터를 실서비스와 동시에 옮기는 작업을 했지만 상황은 호전되지 않았고 더욱이 새로 교체한 서버가 전체 서비스를 중단시키게 만들었고 그후 5시간 동안 다른 방법으로 데이터를 옮기는 작업을 하고 서비스를 리스타팅 했지만 처음과 같은 증상을 보였다. 오후 6시 30분. 결국엔 모든 데이터를 다시 Shards로 reindexing하는 작업을 5시간 동안 실시해 결국 밤 11시 30분에 서비스는 다시 정상으로 돌아오게 했단다. 유실된 데이터는 없다고 말하는데 암튼 일단 발등에 불은 껐다고 한다.

    4sq에서는 MongoDB(v1.6)의 auto-sharding기능을 사용했다고 하는데 커뮤니티에서 이야기하는 걸 보니 원래부터 문제가 있었던 모양이다. 사건 이후 Shards에 서버를 더 추가했고 MongoDB 개발자들과 긴밀하게 작업을 하고 있다고 한다. 또한 이번과 같이 전체 시스템을 다운시키지 않고도 문제를 해결할 수 있도록 부분적 서비스 차단이 가능하도록 적용할 예정이란다. AWS, GAE, Twitter 등의 Status페이지 같은것도 새로 만들어 제공하기 시작했다.

    대강 이렇게 두가지 사례를 요약 정리해 봤다.

    # 에필로그

    나도 한국인 트위터 계정을 수집하고 관리하면서(http://tki.oiko.cc) 다수의 서버를 엮어서 사용하고 있는데 지금까지 166만개의 한국인 계정을 수집하다 보니 그 보다 훨씬 많은 수의 데이터를 저장하고 관리해야 하는 어려움에 봉착하게 되더라. 혼자서 모든 일들을 해야하기 때문에 최대한 서버수를 줄여야 했다. 줄인 서버 수 만큼의 복잡도도 줄어들 수 있기 때문에 새로운 데이터 구조나 서비스 구조가 도입되지 않을 수 없더라. 실제 사용자가 접근하는 부분은 구글 앱엔진의 클라우드 쪽으로 넘겨버리긴 했지만 구글 앱엔진 역시 가용성에서는 100%가 아니기 때문에 여전히 불안한 감은 남아있다. 또, 일단 올린 데이터에 대한 관리부분도 시간이 지나가면서 부담이 커지고 있는것도 사실이다. 지금은 100% 자동화되어 수집과 분석 등이 이루어지고 있고 때가 되면 트위터 계정에 리포팅도 해준다. 리포팅 해주는 자체도 하나의 시스템 운영 모니터링으로 사용하고 있다.

    Big Data시대에 ‘소프트웨어 버그’나 ‘사람의 실수’가 적이 아니라 데이터의 양에 비례한 ‘downtime’이 진정 적이 아닐까 한다. 서비스가 운영하는 데이터의 양이 방대하기 때문에 downtime을 최소화 하려고 해도 데이터의 양에 비례하여 늘어나게 된다. 위에 사례로 든 두가지 경우 모두 서비스 재시동후 데이터를 다시 올리는데 소요되는 시간의 절대치는 데이터 양에 비례할 것이다. downtime을 최소한으로 하는 가장 좋은 방법은 무엇일까? 정답은 없겠지만 downtime을 인정하고 대비해야하는 마음가짐이 아닐까 한다. 이는 전체 시스템의 설계는 물론 통신프로토콜, 서비스 사이의 동기화,  기타 수 많은 종류의 오류나 예외사항에 대한 대비책을 미리 세워두고 준비해 둬야 하는 실행력에 달려있다. 덧붙여 분산 시스템에 대한 이해를 더 공고히 하고 이론적인 배경에서 더 신경을 써야할 것이다. 이론적인 부분에 대해서는 다음에 여유가 되면 정리해볼까 한다.