신뢰할 수 있고 확장 가능하며 유지보수하기 쉬운 시스템을 지탱하는 핵심 아이디어
데이터를 처리하고 저장하는 다양한 기술의 장단점을 검토
라는 소제목이 존재하는 멧돼지 책이다.
별점 4.8/5.0에 이르는 분산 시스템 및 데이터 분야 책의 명작이라고 한다.
책 내용이 쉬운 편이 아니라고 한다. 방대한 분량
데이터 솔루션 회사에서 데이터 엔지니어로 일하던,
어떤 일을 하든지에 해당 내용에 관련된 근본 지식이 정말 중요하다는 말이 많이 들린다.
기술 스택도 중요하지만, 그 기저에 갈린 근본 지식을 알면 더 이해하기 쉽고 잘 사용할 수 있어, 분산 시스템 및 데이터 관련 이론 및 실무 내용이 잘 나와있는 멧돼지 책을 접하게 되었다.
# 전반적 내용
책은 크게 세 파트로 나누어져있다.
이론적으로는 데이터 구조와 핵심 챕터이고, 실무적으로는 마지막이 핵심 챕터이다.
1. 신뢰성, 확장성, 유지 보수성 같은 애플리케이션을 잘 만들기 위해 필요한 특성
RDB, Document DB, Graph DB등 다양한 데이터 모델과 쿼리 랭귀지가 나온다.
SS테이블, LSM 트리, 컬럼 지향 방식 같은 데이터 저장을 위한 데이터 구조
데이터 직렬화9Serialization), 스키마, 프로세스 간 데이터 전달
2. 분산 시스템
시스템을 안정적으로 만들기 위해, 복제와 파티셔닝을 어떻게 할 수 있는지, 이로 인해 장애 복구와 읽기 및 쓰기에 어떤 이슈가 발생할 수 있는지 해결하는 방법이 소개된다.
복제(replication), 파티셔닝, 트랜잭션, 일관성, 합의
각 접근법 별로 어떤 장점이 있고, 어떤 이슈가 발생할 수 있는지 잘 알려준다.
다른 책을 읽어본 사람의 요약을 언급하면,
- ‘트랜잭션’은 RDB를 쓰면서 트랜잭션과 관련된 발생할 수 있는 다양한 이슈 존재
- ‘분산 시스템의 골칫거리 부분’은 네트워크 결함과 시스템의 시계는 믿을 게 못 된다
- ‘일관성과 합의’는 동시에 여러 대상에 쓰기 및 읽기가 가능한 상황에서 어떻게 일관성을 보장할 건지
3. 배치처리, 스트림 처리가 나온 후, 저자가 생각하는 데이터 시스템의 미래
배치처리는 세부내용 보다는 기저에 깔린 철학, 맵리듀스 전반, 이후의 내용이 나온다.
1. 데이터 시스템
어플리케이션은 계산 중심보다, 데이터 중심이 많다.
데이터 중심 어플리케이션이 공통으로 필요로 할 수 있는 기능 : 데이터 시스템
- 데이터 베이스 : 영속성 스토리지
- 캐시 : 읽기 속도 향상, 값비싼 수행 결과 기억
- 검색 색인 : 사용자가 키워드로 데이터를 검색하거나 다양한 방법으로 필터링할 수 있게 제공
- 스트림 처리 : 비동기 처리를 위해 다른 프로세스로 메시지 보내기
- 배치 처리 : 대량의 누적 데이터를 주기 분석
데이터 시스템 범주
- 데이터 베이스, 메세지 큐, 캐시
- 단일 시스템으로는 어플리케이션 니즈를 충족시킬 수 없음. 복합 데이터 시스템으로 흘러감
개발자는 애플리케이션 개발자 + 데이터 시스템 설계자
필요한 고민은,
- 데이터를 정확하고 완전하게 유지하려면?
- 시스템 일부 성능이 저하되어도, 클라이언트에 일관되게 좋은 성능을 어떻게 제공?
- 부하 증가를 다루기 위해 어떻게 규모 확장?
- 서비스를 위해 좋은 API란?
2. 소프트웨어 엔지니어링의 목표
신뢰성(Reliability) : SW결함, human error, 재난 상황
확장성(Scalability) : 트래픽 증가 시 대응 가능
유지보수성(Maintainability) : 모든 개발, 운영자가 생산적으로 작업할 수 있도록 함
3. 신뢰성
결함(fault)를 예측하고 대처할 수 있는 시스템을 내결함성(fault-tolerant) 또는 탄력성(resilient)있다 함
- 결함 : 사양에 벗어난 시스템 구성요소
- 장애 : 유저에게 서비스 제공 못하고 멈춤
결함으로 인해 장애가 발생하지 않도록, 내결함성 구조 설계 필요, 결함을 0으로 줄일 수 없음
3-1. 하드웨어 결함
시스템 장애의 대부분의 원인 : 디스트, 램 고장, 대규모 정전, 담당자 실수
대응 :
- 디스크 :RAID
- 서버 : 이중 전원 디바이스, hot-swap CPU 등
=> 애초에 내결함성과 탄력성을 잘 고려해서 설계
ex) AWS의 가상 장비들은 언제나 죽는 것을 가정하고 설계 :: 재부팅 쉽다.
3-2. 소프트웨어 결함
systematic error는 더 예상하기 어렵고 오류를 더 많이 유발
특정 상황에 의해 발생하기 전까지 나타나지 않을 수 있으며, 명확한 해결책 없음
=> 테스트, 프로세스 격리, 모니터링, 알람 체계 갖추기
3-3. 인적 오류(human error)
대응 방안
- 잘 설계된 추상화 API, 인터페이스 사용
- 실수가 잦을 경우, 실제 데이터로 안전하게 실험해볼 수 있는 sandbox 제공 (stage 환경)
- 단위/통합/수동 테스트 + 코너케이스 유의
- 장애를 빠르게 복구할 수 있도록 도구
- 모니터링 중요
4. 확장성
4-1. 부하 매개변수
부하 성장 질문
- 시스템이 특정 방식으로 커지면 어떤 선택지가 있는지?
- 추가 부하를 다루기 위해 계산 자원을 어떻게 투입?
부하 매개변수 : 정의해야 부하 성장 질문 논의 가능 :: 기준 생김
- 각 시스템 설계에 따라 달라짐
- ex) rps, qps, active user, cache hit ratio 등
트위터 타임라인 아키텍쳐
버전1) 트윗을 쓰면 테이블에 전역적으로 insert, 각 유저는 타임라인 접근 시점에 JOIN
- 쉽고 빠른 쓰기 + 쉽지만 느린 읽기
버전2) 각 유저별 트윗 우편함에 insert, 각 유저는 타임라인 접근 시, 자신의 트윗 우편함만 읽으면 됨
- 어려운 쓰기 + 쉽고 빠른 읽기
- 한계 : 인플루언서가 팔로워가 많으면 쓰기가 너무 비대해지고 어려워 짐
버전3) 인플루언서는 2방식 말고 1방식으로 진행
- 트위터의 부하 매개변수 : 팬아웃 -> 사용자당 팔로워의 분포, 빈도
4-2. 성능 기술하기
하둡같은 일괄 처리 시스템은 처리량에 관심이 있지만, 서비스들은 응답시간에 관심
응답시간은 요청마다 매번 다르기에 분포로 생각
대부분 요청은 빠르지만, 가끔 오래 걸리는 특이점(outlier) 존재
- context switching, 네트워크 패킷 손실 등
응답시간 분석에 백분위 사용, 중앙값(p50)을 지표로 삼는다.
- 특이점 : p96, p99, p999 그 이후는 최적화 비용이 많이 든다.
특이점도 무시할 수 없다. 데이터가 많으면서 중요한 고객일 수 있다.
SLO(서비스 수준 목표, Service Level Objective)와 SLA(서비스 수준 협약서 Service Level Agreement) 가 자주 등장 (??)
큐 대기 지연은 응답시간의 상당 부분 차이
- 선두 차단(head-of-line blockin) : 서버는 병렬로 소수 작업만 처리, 첫 요청 처리시 느려지면 후속 요청이 모두 영향
시스템이 인위적으로 부하를 생성하는 경우, 클라이언트는 응답시간과 독립적으로 요청을 보내야 한다. 응답을 기다리고, 다음 요청을 보내면 평가가 의미없다.
꼬리 지연 증폭(tail latency amplification) : 여러 API를 호출했을 때, 적은 API만 느려도 전체가 느리다.
4-3. 대응 방안
용량 확장 = 수직확장 = scaling up // 규모 확장=수평 확장 = scaling out 사이의 조합
스케일 아웃이 항상 좋지 않는다 -> 적절히 스케일업된 장비들로 구성된게 좋을 수 있다.
탄력적(elastic) : 부하 증가 감지 시 자동으로 자원 추가 -> 항상 좋지는 않는다.
5. 유지보수성
레거시 시스템을 유지보수하는 것을 좋아하지 않으며, 처음부터 레거시를 만들지 않게끔 설계해야 한다.
유지보수성의 원칙
- 운용성 : 운영팀이 원활하게 운영할 수 있도록 쉽게
- 단순성 : 복잡도를 최대한 제거
- 발전성 : 이후 변경에 열려있어야 한다. 요구사항 변경 같은 새로운 사용사례를 쉽게 적용할 수 있어야 한다. (유연성/수정가능성/적응성)
5-1. 운용성
운영 중 일부 측면 자동화
좋은 운영성 : 반복 테스크들을 쉽게 수행할 수 있도록 하는 것
- 런타임 동작과 시스템 내부에 대한 가시성 제공
- 좋은 문서
- 이해하기 쉬운 운영 모델
- admin 등으로 기본값 재정의할 수 있는 권한 부여
- 자기 회복 + 관리자가 상태를 수동으로 제어 가능하도록
5-2. 단순성
시스템이 복잡해지면 모든 사람의 진행을 느리게하고, 유지보수 비용 증가
복잡성 사례 ex)
- 상태 공간의 금증
- 모듈 간 강결합성
- 일관성 없는 네이밍
- 임시방편 코드들
우발적 복잡도(accidental complexity)를 제거하기 위한 최상 도구는 "추상화"
- 좋은 추상화는 깔끔하고 외관 아래로 세부 구현 숨길 수 있음
- 재사용성
5-3. 발전성
시스템 요구사항은 계속 바뀜
애자일(agile) 작업 패턴은 변화에 적응하기 위한 프로세스
- TDD, 리팩토링 등
- 작은 로컬 규모에 초점
참고 및 출처
'공부' 카테고리의 다른 글
[DB] 트랜잭션 ACID란? (Atomicity, Consistency, Durability, Isolation) (0) | 2025.02.10 |
---|---|
[DB] 제 n 정규형(1NF, 2NF, 3NF, BCNF, 4NF, 5NF) (1) | 2025.02.09 |
Large Language Models are Zero-Shot Reasoners 논문 리뷰 (3) | 2025.02.02 |
[Open CV] 색상 곰 탐지 알고리즘 다양한 방법으로 풀기 cv2.HoughCircles, bfs (0) | 2025.01.26 |
Docker 개념 및 핵심 설명, 왜 핫한가? (2) | 2025.01.19 |