728x90

https://product.kyobobook.co.kr/detail/S000001766328

 

 

 

요즘 애플리케이션은 데이터 중심(data- intensive)적

  • 계산 중심(compute-intensive)적이지 않음
  • CPU 성능보다 데이터의 양이나 복잡도, 변화 속도에 영향을 더 많이 받음

시스템 설계 시 엔지니어들은 데이터 저장소 및 엔진을 구상하지 않음

  • 데이터베이스가 데이터 저장 작업을 위해 매우 효율적인 도구이기 때문
  • 다만 시스템 별로 요구사항이 다르기 때문에 다양한 데이터베이스의 특성 및 적용 방법을 고민할 필요가 있음

 

데이터 시스템에 대한 생각

일반적으로 데이터베이스. 큐, 캐시 등을 매우 다른 범주에 속하는 도구로 생각

데이터가 보관되는 시간, 크기 / 데이터를 접근하는 방법 / 지연 시간

 

 

그러면 이 모든 것을 데이터 시스템이라는 포괄적 용어로 묶어야 할까?

  1. 데이터 저장과 처리를 위한 여러 도구들이 최근에 만들어지며 경계가 모호하다
  • 각 도구들이 다양한 유스 케이스에 최적화됐기 때문에 전통적인 분류에 들어맞지 않음
  • 데이터 베이스처럼 지속성을 보장하는 기술(e.g. kafka)등도 등장하고 있기에 경계가 흐려짐
  1. 단일 도구로는 더 이상 데이터 처리와 저장 모두를 만족시킬 수 있는 광범위한 요구사항
  • 간단한 예를 생각해보면 데이터베이스와 캐시를 같이 사용
  • 검색 엔진(서버)를 구성하기 위해 전문 저장(데이터베이스), 색인, 색인을 위한 이벤트 전송(큐)

 

최근의 요구사항을 충족하기 위해서는 하나의 기술만을 사용하는 것이 아니라 여러 기술들을 조합해서 사용하게 되고, 이러한 복합 데이터 시스템을 구축할 필요가 있음

 

 

데이터 시스템이나 서비스를 설계할 때 아래 세 가지 관심사를 중요시 해야 함

  1. Reliability(신뢰성)
  • 결함이 발생했을 때 지속적으로 올바르게 동작(원하는 성능 수준에서 정확한 기능을 수행)
  1. Scalability(확장성)
  • 데이터의 양, 트래픽이 증가할 때 이를 처리할 수 있어야 함
  1. Maintainability(유지보수성)
  • 시스템을 사용하는 모든 사용자가 생산적으로 작업할 수 있어야 함

 

Reliability(신뢰성)

올바르게 동작한다(기대한 대로 동작한다), 무언가 잘못되더라도 지속적으로 올바르게 동작한다.

 

결함(fault)을 예측하고 대처할 수 있는 시스템을 의미함

  • 내결함성(fault-tolerant) 또는 탄력성(resilient)을 지녔다고 표현

 

cf. 신뢰성 vs 가용성

  • 신뢰성: 서비스가 일정 기간동안 얼마나 정상적으로 동작하는지
  • 가용성: 서비스가 얼마나 사용 가능한 상태로 유지되는지 (장애로 인한 중단 시간 최소화)

 

 

결함과 장애(failure)는 동일하지 않음

  • 결함: 정의 또는 사양에서 벗어난 시스템의 한 구성 요소로 정의
  • 장애: 정상적으로 서비스가 제공되지 못 하고 시스템 전체가 중단된 것

결함 확률을 0으로 줄이는 것은 불가능하기에, 결함으로 인해 장애가 발생하지 않도로 설계하는 것이 중요함

 

카오스 엔지니어링처럼 고의적으로 결함을 일으켜 탐지하는 방법도 내결함성을 높이기 위한 좋은 접근 방법

 

 

하드웨어 결함

시스템 장애의 원인을 생각할 때 가장 먼저 생각할 수 있는 결함

  • 화재, 정전으로 인한 장애
  • 물리 장비의 고장

하드웨어 결함으로 인한 시스템 장애를 어떻게 대비해야 할까?

  • 하드웨어 구성 요소에 중복(redundancy)을 추가 (이중화)

 

 

소프트웨어 오류

하드웨어 결함은 무작위적이고 독립적임

  • 어떤 장비에 장애가 발생했을 때 다른 장비에 직접적으로 장애가 전파되지 않음

반면 소프트웨어 오류(시스템 내 체계적 오류)는 예상하기 어렵고, 노드 간 상관관계 때문에 오히려 시스템 오류를 더욱 유발하는 경향이 있음

  • 잘못된 특정 입력이 있을 때 모든 애플리케이션 서버 인스턴스가 죽는 버그
  • 특정 프로세스가 공유 자원(CPU, 메모리, 디스크, 대역폭)을 과도하게 사용
  • 시스템 속도가 느려져 잘못된 응답을 반환하는 서비스
  • 단일 장애 지점(SPOF)

 

소프트웨어 오류로 인한 시스템 장애를 어떻게 대비해야 할까?

  • 시스템 내 상호작용에 대해 고민
  • 지속적인 테스트
  • 프로세스 격리
  • 지속적인 모니터링

 

인적 오류

인적 오류로 인한 시스템 장애를 어떻게 대비해야 할까?

  • 오류의 가능성을 최소하는 방향으로 시스템 설계
    • 잘 설계된 추상화
    • 인터페이스 설계
  • 사람의 실수로 장애가 발생할 수 있는 부분을 분리
    • 샌드박스 제공
  • 지속적인 테스트
    • 단위 테스트부터 통합 테스트까지 모든 수준에 대한 테스트
  • 복구의 용이성
    • 롤백 또는 롤아웃을 쉽고 빠르게
  • 명확한 모니터링 기준 및 대책

 

신뢰성의 중요성

  • 신뢰성은 원자력 발전소나 항공 관제 등 직접적인 안전과 연관된 시스템에만 적용되는 것은 아님
  • 일상적인 애플리케이션에서도 동일하게 안정적으로 작동해야 하며, 이는 서비스의 비용 및 명성에 영향을 줄 수 있음
  • 또한 적은 수의 사용자 및 중요하지 않은 애플리케이션에도 사용자에 대한 책임도 있음

 

 

Scalability(확장성)

증가한 부하에 대처하는 시스템 능력

확장성에 대한 이분법적인 생각이 아닌 시스템이 특정 방식으로 커졌을 때 대처하는 선택, 추가 부하를 다루기 위해 계산 자원을 어떻게 투입하지에 대한 고민이 중요

 

부하 기술하기

시스템의 부하 요소를 간결하게 기술하는 것은 중요함

  • 부하 매개변수(부하의 요인)이 정의되어야 부하가 증가했을 때에 대한 논의를 진행할 수 있음

부하 매개변수는 몇 개의 숫자로 나타낼 수 있는데, 가장 적합한 변수 선택은 시스템 설계에 따라 달라질 수 있음

  • RPS, 데이터베이스의 읽기/쓰기 비율, 활성 사용자 수, cache hits, ...

 

트위터 사례

트윗 작성과 타임라인 조회에 대한 부하

  • 트윗 작성 시 홈 타임라인에서 조회 가능

이를 어떻게 효율적으로 대처해야 하는가

  1. 트윗은 하나, 개별 사용자의 타임라인 조회 시 팔로워 테이블을 모두 조인하여 조회
  2. 트윗을 개별 팔로워의 레코드에 모두 추가, 사용자는 본인의 트윗만 조회

1번 방식의 경우 타임라인 조회에 대한 부하가 매우 큼, 2번 방식의 경우 쓰기 작업을 위한 코스트는 커지지만 타임라인 조회를 매우 수월하게 진행할 수 있음

  • 평균적으로 트윗 게시량(쓰기)보다 타임라인 조회(읽기) 요청량이 수백 백 많기 때문에 2번이 효율적

다만 2번 방식의 경우 팔로워가 적을 때는 문제가 없지만, 팔로워의 수가 극도로 많은 경우 쓰기 작업에 대한 코스트가 매우 커질 수 있음

  • 결국 이 두 가지 접근 방식을 혼합(e.g. 팔로워가 적은 경우 2번 방식, 팔로워가 많은 경우 1번 방식)해서 사용하는 형태를 채택

 

성능 기술하기

아래 질문에 대해서 답하기 위해서는 모두 성능 수치가 필요함

  • 부하가 증가했을 때 시스템 자원(리소스 스펙)을 변경하지 않으면 시스템 성능은 어떻게 영향을 받을까?
  • 부하가 증가했을 때 성능을 유지하기 위해서는 리소스를 어떻게 증가시켜야 할까?

시스템 별로 성능의 기준 및 우선순위는 다름

  • 하둡 같은 일괄 처리 시스템은 처리량이 중요함
  • 일반적인 온라인 서비스는 서비스의 응답 시간이 중요함

 

cf. 응답 시간(response time) vs 지연 시간(latency time)

응답 시간은 클라이언트 관점에서의 시간으로 실제 서비스 시간 외에 네트워크 지연 등 모든 지연을 포함, 지연 시간은 실제 요청이 처리되길 기다리는 시간으로, 서비스를 기다리는 휴지 상태 시간을 의미함

 

 

응답 시간을 확인하기 위해서는 아래의 지표를 활용할 수 있음

  • 평균 응답 시간
  • p50, p95, p99

 

부하 대응 접근 방식

  • 비공유 아키텍처
    • scale up(vertical) vs scale out(horizontal)
  • 탄력성
    • 자동으로 자원을 추가(e.g. HPA) vs 수동으로 확장

 

Maintainability(유지보수성)

소프트웨어 비용의 대부분은 초기 개발이 아닌 지속적인 유지보수에 발생

유지보수 비용을 최소하하기 위해 아래 3가지 원칙을 고려해야 함

  1. 운용성(Operability): 운영자(Operator)가 시스템을 원활하게 운영할 수 있게 쉽게 구현
  2. 단순성(Simplicity): 시스템 복잡도를 최대한 제거해서 새로운 엔지니어가 투입됐을 때 시스템을 이해하기 쉽게 구현
  3. 발전성(Evolvability): 엔지니어가 추후 시스템을 쉽게 변경할 수 있게 구현

 

운용성

운영을 쉽고 빠르게 수행

 

운영 중 일부 측면은 자동화할 수 있고, 자동화해야 함

  • 다만 자동화를 처음 설정하고 제대로 동작하는지 확인하는 일도 사람의 몫

좋은 운영성이란 동일하게 반복되는 작업을 쉽고 빠르게 수행할 수 있게 만들어, 더 가치있는 일에 노력을 집중할 수 있게하는 것

 

단순성

시스템이 복잡해지면 작업 진행 속도가 저하됨

 

시스템이 복잡해지면 모든 사람의 작업 진행 속도가 느려지고, 이는 유지보수 비용의 증가로 이어짐

 

복잡한 시스템은 예산과 일정을 초과시키고, 버그가 유발할 가능성이 증가됨

 

복잡도를 제거하기 위한 좋은 도구는 추상화

  • 좋은 추상화는 외관을 깔끔(세부 구현을 숨겨 복잡함을 제거)하게 하고, 재사용성을 증가시킴

 

발전성

새롭고 변경되는 요구사항에 대해 유연하게 대처할 수 있어야 함

 

시스템 요구사항은 계속 바뀌기에, 이러한 변경 사항을 민첩하게 대처할 수 있어야 함

 

 

Appendix

분산 데이터베이스에서 CAP 이론

  • Consistency(일관성): 사용자가 분산 데이터베이스 상의 어떤 노드와 통신하는지 상관없이 같은 데이터를 조회할 수 있는 것
  • Availability(가용성): 모든 요청이 응답을 받을 수 있어야 한다는 것을 의미
  • Partition Tolerance(분할 허용성): 시스템 내 분할이 생겼을 때 시스템이 여전히 작동하는 것을 의미

CAP를 모두 충족할 수 있는 시스템은 없음. 하지만 분산 환경에서는 Partition Tolerance는 필수적임

728x90

+ Recent posts