본문 바로가기
Etc.

장애 전파를 방지하기 위한 Circuitbreaker로 조회수 백업시스템 만들기

by Jammini 2025. 8. 17.
728x90

목차

  1. 개요
  2. 조회수 설계
  3. Circuit breaker
  4. 주의 할 점
  5. 그렇다면 어떻게 적용하는 것이 좋을까?
  6. 더 나아가기

1. 개요

프로젝트를 진행하면서 각각의 게시글에 대한 조회수를 어떻게 처리할까 고민을 하였다.

게시글 중 인기 게시글의 경우 조회수를 Database로 올리게 된다면, DB의 부하가 심해질거를 예상하여 Redis 캐시를 도입하였다.

이때 운영중인 Redis에 장애가 생긴다면 조회 요청이 실패할 뿐 아니라 지연된 응답으로 다른 서비스들에게도 영향을 미칠 수 있다.

2. 조회수 설계

게시글의 댓글, 좋아요 수의 경우 관계형 데이터베이스를 사용해 데이터의 일관성을 지키고 안전한 저장소에 영구적으로 저장했다. → 하지만 디스크 접근 비용과 트랜잭션 관리 비용이 크다.

 

반면, 조회수는 데이터 일관성이 덜 중요하고 트랜잭션이나 안전한 저장소가 반드시 필요하지 않다. → 트래픽이 많으므로 접근 비용이 비싼 디스크보다는 빠른 저장소를 고려한다.

  • 데이터 일관성
    • 좋아요 수/댓글 수와 같은 카운트에 비해 비교적 덜 중요하다.
    • 모든 조회 내역을 사용자에게 보여주는게 아니기 때문에 데이터 불일치가 발생하더라도 사용자가 인지하기 어렵다.
  • 쓰기 트래픽
    • 게시글의 댓글이나 좋아요 : 비교적 적음
      • 사용자가 직접적인 액션에 의해 쓰기 작업이 필요하다.
    • 조회수 : 비교적 많음
      • 단순히 게시글을 조회만 해도 쓰기 작업이 필요하다.

결론적으로, 조회수는 데이터의 일관성이 크게 중요하지 않고, 트래픽이 아주 많을 수 있다. 그래서 조회수를 관리하기 위해 캐시를 사용하였다.

3. Circuit breaker

Redis의 장애가 발생하면 다른 방법을 활용해서 문제를 해결할 수 있는데 그것이 바로 Circuit breaker이다.

전기회로에서 회로차단기는 과부하를 막기 위해 자동으로 회로를 열어 전류의 흐름을 차단하는 것처럼 애플리케이션에서 과부하러 인한 장애가 다른 곳으로 전파되지 않도록 할 수 있다.

 

4. 주의 할 점

Redis에 장애가 생겨 Circuit이 오픈 된 상황이라면 Database를 바라보도록 코드를 작성했었다.

이대로 진행된다면 레디스에 장애가 발생하여 Circuit이 오픈 되었을 때, DB에 조회수를 읽고 쓰는 요청이 늘어날 것이다.

레디스에서 발생한 장애가 빠르게 회복되어 Circuit이 빠르게 닫힌다면 다행이지만 복구가 늦어진다면 DB를 먹통으로 만들고 서비스 전체를 마비시키는 문제를 발생시킬 수 있다.

잘 생각해보면 레디스 캐시의 존재 이유는 DB부하를 줄이기 위해서 이다. 그렇기에 fallback으로 DB에 조회 요청을 날리는 것은 장애를 그대로 시스템 전체에게 전파하는 것과 다를 바 없다.

5. 그렇다면 어떻게 적용하는 것이 좋을까?

아래의 초점을 맞춰 조회 수 관련하여 설계를 적용했다.

  1. 가용성 : Redis 장애/지연 시에도 정상 동작한다.
  2. 유실 최소화 : 장애 구간의 카운트는 최대한 보전한다.
  • Circuit이 CLOSED인 경우

기본적으로 Redis에서 조회수를 누적시키다가 일정 시간이 되면 DB에 업데이트 되는 구조이다.

하지만 Redis에 장애가 터지게 되면 Circuit이 열러 아래와 같은 구조가 된다.

  • Circuit이 OPEN인 경우

장애 복구가 될 때까지 별도의 Map을 이용해 게시글마다 게시글 조회수를 증가해놓고 기존 조회수를 더해주는 로컬캐시를 만들어 임시로 운영하는 것을 고려하였다.

이렇게 진행한다면 클라이언트가 시스템에서 발생한 문제를 인지하지 못할수도 있을 것이다.

 

6. 더 나아가기

서킷브레이커를 이용해 장애가 발생하더라도 가용성과 유실을 최소화하기 위해 위에 방식을 적용해 보았다.

조회 수 데이터가 유실이 되어서는 안되고 일관성을 유지해야하는 데이터라면 DB를 이용해 동기적으로 누적을 시키는 방법을 사용하는 것이 일반적일 것이다.

 

  • 요청마다 DB에 직접 UPDATE post SET view_count = view_count + 1 WHERE id=? 를 한다.
  • 장점: 유실 없음, 즉시 반영
  • 단점: 트래픽이 몰리면 DB가 병목

만약, 대용량 트래픽까지 안정적으로 처리하려면 메세지 큐로 비동기 처리를 하면 베스트 선택이 될 것이다.

  • 요청은 DB까지 가지 않고 MQ에 적재하여 서버 부담 ↓
  • 컨슈머가 모아서 DB 반영 (UPDATE ... SET view_count = view_count + n)
  • 장점: 대규모 트래픽 흡수, 유실 방지
  • 단점: 실시간 반영이 되지 않고 지연이 일어남

위와 같이 여러가지를 고려해가며 프로젝트 상황에 맞게 트레이드 오프를 고려해가며 설계를 하면 좋은 프로젝트가 될 것이라 생각한다.

 

 

반응형