본 글은 데이터 중심 어플리케이션(마틴 클레프만)으로 스터디하며 해당 책의 내용을 요약 정리한 내용입니다.
https://github.com/ddia-study/ddia-study
computive-intensive <<< data-intensive
첫 번째 이유
데이터 저장과 처리를 위한 여러 새로운 도구는 최근에 만들어졌다.
새로운 도구들은 다양한 use case에 최적화됐기 때문에 더 이상 전통적인 분류에 딱 들어맞지 않는다.
두 번째 이유
점점 더 많은 애플리케이션이 단일 도구로는 더 이상 데이터 처리와 저장 모두를 만족시킬 수 없는 과도하고 광범위한 요구사항을 갖고 있다.
이제부터 개발자는 애플리케이션 개발자뿐만 아니라 데이터 시스템 설계자이기도 하다.
이 모든 것이 올바르게 동작함을 의미하는 경우,
대략 무언가 잘못되더라도 지속적으로 올바르게 동작함을 신뢰성의 의미로 이해할 수 있다.
잘못될 수 있는 일을 fault라고 부른다. 그리고 이를 예측하고 대처할 수 있는 시스템을 fault-tolerant 혹은 resilient를 지녔다고 말한다.
fault는 failure와 동일하지 않다.
fault는 사양에서 벗어난 시스템의 한 구성 요소로 정의되지만, 장애는 사용자에게 필요한 서비스를 제공하지 못하고 시스템 전체가 멈춘 경우다.
많은 중대한 버그들이 미흡한 오류 처리에 기인한다. 따라서 고의적으로 결함을 유도해서 내결함성 시스템을 테스트 한다. e.g. Chaos Monkey
하드디스크의 MTTF는 10 ~ 50년. 따라서 10000개의 디스크로 구성된 저장 클러스터는 평균적으로 하루에 한 개의 디스크가 죽는다고 예상해야 한다.
이를 해결하기 위해 하드웨어 구성 요소에 중복을 추가한다. 고장난 구성 요소의 교체 시간 동안 중복 구성 요소를 대신 사용한다.
데이터 양과 애플리케이션의 계산 요구가 늘어나면서 더 많은 애플리케이션이 많은 수의 장비를 사용하게 됐고 이와 비례해 하드웨어 결함율도 증가했다.
또한 AWS 같은 일부 클라우드 플랫폼은 인스턴스가 별도의 경고 없이 사용할 수 없게 되는 상황이 상당히 일반적이다.
따라서 소프트웨어 내결함성 기술을 사용하거나 하드웨어 중복성을 추가해 전체 장비의 손실을 견딜 수 있는 시스템으로 점점 옮겨가고 있다.
소프트웨어 결함을 유발하는 버그는 특정 상황에 의해 발생하기 전까지 오랫동안 나타나지 않는다.
소프트웨어의 체계적 오류 문제는 신속한 해결책이 없다.
사람은 미덥지 않다. 시스템을 어떻게 신뢰성 있게 만들까?
"중요하지 않은" 애플리케이션도 사용자에 대한 책임이 있다.
확장성은 증가한 부하에 대처하는 시스템 능력을 설명하는 데 사용하는 용어지만, 시스템에 부여하는 일차원적인 표식이 아니다.
"시스템이 특정 방식으로 커지면 이에 대처하기 위한 선택은 무엇인가?"
"추가 부하를 다루기 위한 계산 자원을 어떻게 투입할까?"
시스템의 현재 부하를 간결하게 기술해야, 부하 성장 질문을 논의할 수 있다.
부하는 부하 매개변수(load parameter)라 부르는 몇 개의 숫자로 나타낼 수 있고, 시스템 설계에 따라 적합한 변수가 달라진다.
e.g. 웹 서버의 초당 요청 수, 데이터베이스의 읽기 대 쓰기 비율, 대화방의 동시 활성 사용자, 캐시 적중률
시스템 부하를 기술하면 부하가 증가할 때 어떤 일이 일어나는지를 조사할 수 있다.
두 질문 모두 성능 수치가 필요하다. 잠깐, 성능 수치?
일괄처리 시스템은 throughput을, 온라인 시스템에서는 response time을 중요하게 여긴다.
Response Time
특히 response time은 매번 달라지기 때문에 단일 숫자가 아닌 측정 가능한 값의 분포로 생각해야 한다.
사용자가 보통 얼마나 오랫동안 기다려야 하는지 알고 싶다면 중앙값(p50)이 좋은 지표다.
사용자 요청의 절반은 중앙값 미만으로, 절반은 중앙값보다 오래 걸린다.
참고로 tail latency라고 알려진 p95, p99, p999를 보는 것은 서비스의 사용자 경험에 직접 영향을 주기 때문에 중요하다.
SLO vs SLA
이미지 출처 : https://www.atlassian.com/incident-management/kpis/sla-vs-slo-vs-sli
Queueing delay
높은 백분위에서 응답 시간의 상당 부분을 차지한다.
서버는 병렬로 소수의 작업만 처리할 수 있기 때문에, 소수의 느린 요청 처리만으로도 후속 요청 처리가 지체된다.
이 현상을 선두 차단(head-of-line blocking)이라고 한다.
부하 매개변수가 어느 정도 증가하더라도 좋은 성능을 유지하려면 어떻게 해야 할까?
scaling up(vertical scaling) vs scaling out(horizontal scaling)
다수의 장비에 부하를 분산하는 아키텍처를 비공유(share-nothing) 아키텍처라고 부른다.
단일 장비에서 수행될 수 있는 시스템은 보통 간단하지만, 고사양 장비가 비싸기 때문에 대부분은 스케일 아웃을 한다.
일부 시스템은 탄력적(elastic)이다. 부하 증가를 감지하면 컴퓨팅 자원을 자동으로 추가할 수 있다.
다수의 장비에 stateless 서비스를 배포하는 것은 간단하지만, stateful 시스템을 분산 설치하는 것은 매우 복잡하다.
따라서 최근까지는 데이터베이스를 분산으로 만드는 등의 고가용성 요구가 있을 때까지 단일 노드에 DB를 유지해왔다.
그렇지만 분산 시스템을 위한 도구나 추상화가 좋아지면서 조금씩 바뀌고 있다.
대개 대규모로 동작하는 시스템 아키텍처는 해당 시스템을 사용하는 애플리케이션에 특화되어 있다.
one-size-fits-all은 없다.
특정 애플리케이션에 적합한 확장성을 갖춘 아키텍처는 주요 동작이 무엇이고 잘하지 않는 동작이 무엇인지에 대한 가정을 바탕으로 구축한다.
이 가정은 곧 부하 매개변수가 된다.
소프트웨어 비용의 대부분 = 유지보수
유지 보수는 고통스럽지만, 고통을 최소화하고 레거시를 직접 만들지 않게끔 소프트웨어를 설계할 수 있다.
*"좋은 운영은 종종 나쁜 소프트웨어의 제약을 피하는 대안이 될 수 있다. 하지만 좋은 소프트웨어라도 나쁘게 운영할 경우 작동을 신뢰할 수 없다."*
시스템을 지속해서 원활하게 작동하려면 운영 팀이 필수다. 보통 이런 작업을 책임진다.
좋은 운영성이란 반복 태스크를 쉽게 수행할 수 있게끔 만든다. 데이터 시스템은 다양한 일을 할 수 있다.
복잡도의 다양한 증상
복잡한 소프트웨어에서는 변경이 있을 때 버그가 생길 위험이 더 크다.
단순성이 구축하려는 시스템의 핵심 목표여야 한다.
시스템을 단순하게 만드는 일은 기능을 줄인다는 것이 아니라, 우발적 복잡도(accidental complexity)를 줄인다는 뜻일 수 있다.
이런 우발적 복잡도를 제거하기 위해 추상화를 사용할 수 있다.
좋은 추상화는 많은 세부 구현을 깔끔하게 숨길 수도 있고, 재사용성이 높다.
시스템의 요구사항이 영원히 바뀌지 않을 가능성은 매우 적다.
조직 프로세스 측면에서 agile 작업 패턴은 변화에 적응하기 위한 프레임 워크를 제공한다.
또한 애자일 커뮤니티는 TDD, Refactoring 같이 자주 변화하는 환경에서 도움이 되는 기술 도구와 패턴을 개발하고 있다.
데이터 시스템 변경을 쉽게 하고 변화된 요구사항에 시스템을 맞추는 방법은 시스템의 간단함과 추상화와 밀접하다.
안타깝게도 애플리케이션을 신뢰할 수 있고 확장 가능하며 유지 보수하기 쉽게 만들어주는 간단한 해결책은 없다.
하지만 여러 애플리케이션에서 계속 재현되는 특정 패턴과 기술이 있다.
Chapter 8. 분산 시스템의 골칫거리 - Part 2 (0) | 2022.06.10 |
---|---|
Chapter 8. 분산 시스템의 골칫거리 - Part 1 (0) | 2022.06.10 |
Chapter 6. Partitioning(파티셔닝) (0) | 2022.06.10 |
Chapter 5. Replication(복제) (0) | 2022.06.10 |
Chapter 3. Storage and Search (0) | 2022.06.10 |
댓글 영역