장애 상황 : DB lock, DB 복제지연, 메모리 릭, 캐시 압력

haruceki·2024년 8월 21일

DB lock

DB Lock은 데이터베이스에서 동시에 여러 트랜잭션이 동일한 데이터를 수정하거나 접근할 때 데이터의 무결성과 일관성을 보장하기 위해 사용되는 메커니즘이다. 데이터의 일관성과 무결성을 유지하기 위해 특정 트랜잭션이 데이터를 수정하는 동안 다른 트랜잭션이 해당 데이터에 접근하거나 수정하지 못하도록 잠그는 기능.

잠금의 분류

잠금의 범위에 따른 분류로는 행 잠금, 테이블 잠금, 페이지 잠금, 테이블스페이스 잠금 등이 있다. 이외에도 잠금 모드에 따라 분류도 가능하다.

  • 공유 잠금 (Shared Lock, S Lock)
    데이터를 읽기 위한 잠금이다.
    여러 트랜잭션이 동시에 동일한 데이터를 읽을 수 있지만, 데이터를 수정할 수는 없다.
    읽기 작업에서는 충돌이 발생하지 않지만, 수정 작업과는 충돌이 발생할 수 있다.

  • 배타적 잠금 (Exclusive Lock, X Lock)
    데이터를 수정하기 위한 잠금이다. 잠금을 걸면 다른 트랜잭션은 해당 데이터에 대한 읽기 및 쓰기 작업을 할 수 없다. 하나의 트랜잭션이 데이터를 수정하는 동안 다른 트랜잭션이 그 데이터에 접근하지 못하게 한다.

  • 갱신 잠금 (Update Lock, U Lock)
    데이터 갱신 작업을 위해 사용되는 잠금으로, 처음에는 공유 잠금으로 설정되지만, 실제 데이터가 수정되기 직전에 배타적 잠금으로 변경된다. 교착 상태(Deadlock)를 줄이기 위해 사용된다. 예를 들어, SELECT 문 후 UPDATE 작업이 발생할 때, 갱신 잠금을 사용하면 다른 트랜잭션이 동일 데이터를 수정하려고 할 때 잠금 충돌을 방지할 수 있다.

  • 의도 잠금 (Intent Lock)
    테이블이나 행에 대해 잠금을 설정할 의도가 있음을 표시하는 잠금이다. 상위 수준의 잠금이 설정되기 전에 하위 수준에서 어떤 잠금을 사용할지 나타낸다.
    의도 공유 잠금 (IS Lock), 의도 배타적 잠금 (IX Lock), 의도 공유-배타적 잠금 (SIX Lock)으로 분류된다.

  • 명명된 락 (Named Lock)
    데이터베이스에서 특정 이름으로 락을 설정하여, 동시에 하나의 프로세스만 특정 리소스에 접근하도록 하는 방식으로, 주로 특정 리소스나 작업에 대한 접근을 직관적으로 제어하기 위해 사용됩니다.

  • 분산 락 (Distributed Lock)
    분산 락은 여러 시스템이나 인스턴스에서 동시에 동일한 자원에 접근할 때, 자원의 일관성을 유지하기 위해 사용되는 락입니다. Redis와 같은 분산 시스템에서 사용된다.

  • 옵티미스틱 잠금 (Optimistic Lock)
    데이터의 변경 가능성을 낮게 보고 잠금을 사용하지 않는 방식. 데이터 수정 시점에 충돌이 발생하면 예외를 발생시켜 트랜잭션을 롤백한다. 주로 버전 번호(Version Number)를 사용하여 충돌을 감지한다.

  • 비관적 잠금 (Pessimistic Lock)
    데이터의 변경 가능성을 높게 보고, 데이터에 접근할 때마다 잠금을 거는 방식이다. 트랜잭션이 완료될 때까지 다른 트랜잭션의 접근을 방지한다. 주로 데이터베이스 레벨에서 동작한다. repository에서 @Lock 어노테이션으로 설정할 수 있다.

데드락

데이터베이스 환경에서 데드락은 두 개 이상의 트랜잭션이 서로가 점유하고 있는 자원을 기다리면서 무한 대기 상태에 빠지는 상황. 데드락 상황이 발생하면 해당 트랜잭션들은 더 이상 진행될 수 없고, 시스템 성능에 큰 영향을 미칠 수 있으므로 주의해야 한다.
데드락이 발생할 경우를 대비하여 타임아웃 결정을 하여 전체 시스템이 다운되는 것을 막아야 한다.

DB 복제 지연(Database Replication Lag)

복제지연은 쓰기 DB와 읽기 DB가 나뉘어져 있을 때 데이터가 쓰기 DB에서 읽기 DB로 복제되는 과정에서 발생하는 시간 지연을 의미한다. 이 지연은 여러 가지 이유로 발생할 수 있으며, 복제본 데이터베이스의 데이터가 마스터 데이터베이스와 일치하지 않을 수 있는 잠재적 문제를 야기한다.

복제 지연의 원인으로는 트랜잭션 처리 속도 차이, 네트워크 지연, 복제본의 성능 문제, 대용량 트랜잭션이 처리될 경우 성능 문제, 비동기 복제 설정 등으로 발생할 수 있다.

복재 지연의 해결 방안으로는 복제본 성능 향상을 위한 하드웨어적 업그레이드, 쓰기 후 즉시 읽기를 시도할 경우 잠시 지연을 두고 읽기를 재시도하는 지연 적용 알고리즘(Lag Compensating Logic) 적용, Command Query Responsibility Segregation (CQRS) 패턴을 적용, 캐시 시스템 도입, 네트워크의 대역폭을 늘리는 등의 개선, 복제 설정의 최적화, 동기 복제 사용, 모니터링 및 알림 시스템 구축 등이 있다.

메모리 릭(Memory Leak)

메모리 릭은 프로세스가 더 이상 필요하지 않은 메모리를 할당한 후 이를 해제하지 않음으로써, 해당 메모리가 지속적으로 점유된 상태로 남아있는 현상. 이러한 메모리 릭은 메모리 사용량을 지속적으로 증가시켜 시스템의 메모리를 고갈시켜 성능 저하 또는 애플리케이션의 충돌 또는 프로그램의 비정상 종료 등의 문제를 발생시킬 가능성이 있다.

메모리 릭의 원인으로는 객체 참조 해제 누락, 이벤트 리스너 및 콜백 미해제, 잘못된 캐시 관리, 비순환 참조, 네이티브 자원 관리 실패, 스프링 빈의 라이프사이클 관리 문제, @Autowired 주입된 객체의 잘못된 관리, threadLocal의 잘못된 사용 등이 있다.

메모리 릭 방지 방법은 객체 참조 관리, 약한 참조를 사용하기, 이벤트 리스너 제거, 정기적인 메모리 검사, 네이티브 자원 해제(try-catch 사용)를 해야 한다.

캐시 압력(Cache Pressure)

캐시 압력은 컴퓨팅 시스템에서 캐시 메모리가 가용 용량에 도달하거나 부족해져, 캐시에 저장된 데이터나 항목을 유지하는 것이 어려워지는 상황을 말한다. 캐시 압력이 증가하면 캐시 항목을 삭제하거나 새 데이터를 캐시에 저장하는 동안 대기 상태가 발생할 수 있다. 따라서 캐시 압력은 메모리 관리 및 성능 최적화와 밀접하게 관련되어 캐시가 과부하 상태에 이를 때 시스템 성능 저하를 초래할 수 있다.

캐시 압력은 데이터량 증가, 캐시 크기 제한에 따른 캐시 용량 초과, 비효율적 캐시 전략, 사용자별 캐시 공간 경쟁, 캐시 히트율 저하 등으로 발행한다.

캐시 압력이 발생할 경우 성능이 저하되고, 캐시 미스가 증가하여 지연이 발생하며 높은 I/O 부하와 전체 시스템 부하에 영향이 있ㅆ으며 데이터의 일관성 문제가 생길 수 있다.

캐시 압력 관리 방법으로는 캐시 크기 조정(최대 크기 설정), 캐시 제한 설정, 효율적인 캐시 교체 정책, 캐시 히트율 개선, 동시 작업 수 제한이나 부하분산을 통한 분산 캐시 사용, 캐시 우회 전략, 모니터링 및 조정, 데이터 압축 등의 방법이 있다.

캐시 백오프(Backoff) 전략

캐시 백오프는 캐시 시스템에서 과부하나 성능 저하를 방지하기 위해 요청 처리 속도를 조절하는 전략이다. 캐시 백오프는 주로 캐시 서버가 과도한 요청을 받거나 캐시 미스가 증가하는 상황에서, 시스템 전체의 성능과 안정성을 유지하기 위해 사용된다.

캐시 백오프 전략을 사용할 경우, 캐시가 일시적으로 사용되지 않게 되면서 모든 요청이 데이터베이스로 직접 전달될 수 있다. 이로 인해 데이터베이스에 과부하가 발생하고, 성능 저하나 시스템 장애가 일어날 가능성이 있다. 이 경우 db 연결 대신 500에러를 던져 지금은 사용할 수 없다고 막고 다른 서비스로 장애가 퍼지는 걸 막아야 한다.

profile
희망도 절망도 없이 매일 코딩을 한다.

0개의 댓글