IL-0430 Hatena · 2018-09-26database
Redis 장애 조치 뒤 Mackerel 전체가 느려지고 생존 여부 감시가 4시간 넘게 멈췄다
2018년 9월 26일 Mackerel 팀은 감시 데이터를 담는 Redis 의 메모리 사용량이 늘어나는 것을 보고 Redis 를 스케일업하기로 했고, 그 준비로 복제를 구성했다. 복제 구성이 오래 걸리면서 Redis 가 응답하지 않는 시간이 생겼고, 클러스터링 소프트웨어인 keepalived 가 이를 노드 고장으로 보고 10시 51분에 장애 조치를 일으켰다. 애플리케이션 서버는 Redis 에 접속하지 못해 올바른 응답을 내지 못했고, Mackerel 시스템 전체가 불안정해지며 생존 여부 감시가 멈췄다.
10시 55분 팀이 Redis 를 올바른 쪽으로 다시 전환해 애플리케이션이 돌아온 것을 잠시 확인했다. 하지만 장애 전부터 있던 네트워크 불안정과 Redis 메모리 증가가 겹치면서 애플리케이션 서버의 지연 시간이 나빠지고 타임아웃이 이어졌다. 애플리케이션 서버를 차례로 재시작해도 나아지지 않았고, 이것이 장애가 길어진 이유였다. 11시부터 14시 50분까지 팀은 부적절한 메트릭을 보내는 Mackerel 조직의 요청을 막고 타임아웃 간격을 조정했다. 또 TSDB 인 Diamond, Kinesis 샤드 수, Redis Cluster 샤드 수, API 애플리케이션 서버를 늘렸다. 그 뒤 잠시 점검 모드로 바꿔 사내에서 확인하고 외부 요청을 조금씩 되돌렸고, 15시 20분 복구를 선언했다.
장애의 발단은 Redis 작업에 따른 의도하지 않은 장애 조치였다. 복구가 길어진 원인은 정확히 밝혀지지 않았다. 회고에서는 특정 접근 패턴이 이어질 때 Scala 애플리케이션에서 스레드 풀이나 커넥션 풀의 동기화 대기 또는 락 경합 때문에 지연 시간이 나빠진다는 가설이 나왔다. 격리된 환경에서 장애 상황을 재현하려 했지만 재현되지 않았고, 원인 조사는 중단했다.
- 심각도
- –
- 영향 범위
- The whole Mackerel service malfunctioned and alive monitoring stopped from 10:51 to 15:20 JST
- 영향 사용자
- –
- 지역
- –
- 감지까지
- –
- 복구까지
- 4h 29m
증상
10시 51분 Redis 에 장애 조치가 일어난 뒤 애플리케이션 서버가 Redis 에 접속하지 못해 Mackerel 이 요청에 제대로 응답하지 못했다. Mackerel 시스템 전체가 불안정해졌고 생존 여부 감시가 멈췄다.
Redis 를 올바른 쪽으로 다시 전환하자 애플리케이션이 잠시 되살아난 것처럼 보였다. 그러나 동작이 안정되지 않았고, 애플리케이션 서버의 지연 시간이 나빠지고 타임아웃이 났다.
장애 전부터 네트워크 상태가 좋지 않았고 Redis 메모리 사용량도 늘고 있었다. 팀은 애플리케이션 서버를 차례로 재시작했지만 증상은 나아지지 않았다.
복구 단계에서는 mackerel-agent 가 메트릭을 다시 보내고 있었고, TSDB 에 메트릭이 늦게 반영되었다. 팀은 애플리케이션 서버의 응답이 안정되고 이 재전송이 잦아들고 반영 지연이 풀린 것을 보고 15시 20분에 복구를 선언했다.
원인
- 촉발
- 감시 데이터를 담는 Redis 를 스케일업하려고 복제를 구성하는 작업을 했다. 복제 구성에 시간이 걸리는 동안 Redis 가 응답하지 않았고, keepalived 가 이를 노드 고장으로 판단해 의도하지 않은 장애 조치를 일으켰다.
감지
–
조치
- Redis 를 올바른 쪽으로 다시 전환하고 애플리케이션이 돌아온 것을 잠시 확인했다.
- 애플리케이션 서버를 차례로 재시작했지만 증상은 나아지지 않았다.
- 부적절한 메트릭을 보내는 Mackerel 조직을 찾아 그 요청을 차단했다.
- 애플리케이션 서버의 타임아웃 간격을 조정했다.
- TSDB 인 Diamond 를 임시로 증설했다.
- Kinesis 샤드 수와 Redis Cluster 샤드 수를 늘렸다.
- API 용 애플리케이션 서버를 스케일아웃했다.
- 잠시 점검 모드로 바꿔 사내에서 확인한 뒤 외부 요청을 조금씩 되돌렸다.
후속 조치
- 짧은 부하 증가로는 장애 조치가 일어나지 않도록 Redis 의 keepalived 헬스 체크 횟수를 늘렸다.
- 애플리케이션 성능에 여유를 두려고 Redis 를 스케일업했다.
- 애플리케이션 서버 대수를 늘렸다.
- 애플리케이션을 고쳐 필요한 감시 데이터만 Redis 에 저장하게 해 Redis 메모리 사용량을 줄였다.
- 부적절한 API 요청을 빨리 찾아내 대시보드에서 볼 수 있는 체계를 만들었다.
- 부적절한 요청을 보내는 조직을 빨리 차단하는 기능을 만들었다.
- 부적절한 요청을 더 정확히 찾아내고 API Limit 같은 기능을 더하는 것을 검토한다.
- 애플리케이션 서버의 내부 처리 모니터링을 강화해 장애가 나기 전에 대응할 수 있게 한다.
교훈
Hatena 는 상세한 원인을 밝히지 못했다. 그래도 장애 조치 오작동을 막고, 애플리케이션 성능에 여유를 더 두고, Redis 에 저장하는 데이터를 줄이고, 부적절한 요청을 빨리 찾아 막으면 이번처럼 긴 장애는 막을 수 있다고 보았다. 장애가 나더라도 영향이 좁은 범위에 그치도록 하는 작업을 이어 가겠다고 했다.
출처
관련 사례
같은 원인 · 공통 데이터베이스 복제, 인메모리 캐시
IL-0063Redis 스테이트풀셋을 다시 만들자 Redis 클러스터가 한꺼번에 재시작되며 일부가 망가졌고, 재연결 폭주로 백엔드가 OOM 으로 죽어 AdGuard VPN 이 약 50분 멈췄다.AdGuard VPN · 2025같은 원인 · 공통 인메모리 캐시
IL-0392데이터센터 전환을 앞두고 원형 복제를 설정하던 중 Wikimedia x1 섹션의 eqiad·codfw 사이 MariaDB 복제가 6분 멈췄다Wikimedia Foundation · 2024같은 원인 · 공통 데이터베이스 복제
같은 원인 · 공통 데이터베이스 복제
IL-0367Central US 의 Azure Storage 가 VM 디스크 요청을 거부해 VM 과 그 위의 SQL Database, Cosmos DB 가 멈췄다Microsoft Azure · 2024같은 원인 · 공통 데이터베이스 장애 조치 관리자
같은 원인 · 공통 데이터베이스 복제
같은 원인 · 공통 인메모리 캐시
같은 원인 · 공통 데이터베이스 복제
내 클러스터에도 있는지 확인하기
AI 도구와 스크립트용
- 이 사례의 JSON: https://incidentlib-api.benchlet.com/cases/IL-0430
- 가장 비슷한 사례들: https://incidentlib-api.benchlet.com/cases/IL-0430/similar
- MCP 서버(Streamable HTTP, 키 없음):
https://incidentlib-mcp.benchlet.com/mcp
API 는 키가 필요 없습니다. MCP 서버는 search_incidents, get_incident, list_incidents, get_topic, vocab 도구를 내놓습니다. 사용법은 API 와 MCP.