데이터 중심 애플리케이션은 어떤 기능을 공통으로 필요할까?
- 데이터베이스 : 나중에 다시 데이터를 찾을 수 있도록 저장
- 캐시: 읽기 속도 향상을 위해 값이 비싼 수행 결과를 기억
- 검색 색인: 사용자가 데이터를 검색할 수 있는 기능 제공
- 스트림 처리: 비동기 처리를 위해 다른 프로세스로 메시지 보내기
- 일괄 처리: 주기적으로 대량의 데이터 분석
신뢰성, 확장성, 유지보수성
대부분의 소프트웨어 시스템은 신뢰성, 확장성, 유지보수성에 관심이 많다.
엔지니어링 관점에서 이 3가지를 어떻게 생각해야하는지 알려주겠다. (다음 장에서는 이를 잘 지키기위한 방법에 대해 말할 것이다.)
신뢰성
: 무언가 잘못되더라도 지속적으로 올바르게 동작해야한다.
올바르게 동작해야한다는 것은?
- 사용자가 기대한 기능을 수행해야 한다.
- 사용자의 실수나 예상치 못한 사용법을 허용할 수 있다.
- 예상된 부하나 데이터 양에서 충분히 동작해야 한다.
- 비허가 접근과 오남용을 방지해야 한다.
신뢰성을 높이기 위해서는?
1. 결함으로 인한 장애를 최소화하자
- 결함은 잘못될 수 있는 일을 말하고, 장애는 필요한 서비스를 제공하지 못하고 시스템이 멈춘 경우이다.
- 결함이 장애로 이어지지 않도록 내결함성 구조를 설계하자 (이 책에서 알려주겠다)
2. 결함을 예측하고 대처할 수 있는 내결함성(fault-tolerant) or 탄력성(resilient) 을 갖추자
- 일부러 결함을 발생시키는 훈련과 테스트(ex. 카오스 몽키) 를 하자
- 보안이 뚫려 개인정보가 털린다면 해결책이 없는 결함이다. (이 책에서는 해결책이 있는 결함 유형을 다루겠다.)
결함의 종류는?
1.하드웨어 결함
: 하드디스크 고장, 램 결함, 정전, 네트워크 케이블 뽑기
이 결함을 대응하는 방법
- 중복(redundancy) 구축 - 하나가 죽으면 교체될 수 있도록
- 디스크 RAID 구성, 이중 전원 디바이스, 핫 스왑 가능한 cpu, 예비 건전지
2. 소프트웨어 오류
: 시스템 내 체계적 오류 (systematic error)
※ 비체계적 오류: 무작위 오류
어떤 오류가 sw 오류일까?
- 잘못된 특정 입력이 있을 때 죽는 버그
- 공유 자원(cpu시간, 메모리, 디스크, 네트워크 대역폭) 을 과도하게 사용하는 일부 프로세스
- 시스템 속도가 느려져 반응이 없거나 잘못된 응답 반환
- 작은 결함이 다른 결함을 야기해 차례차례 더 많은 결함이 발생되는 연쇄 장(cascading failure)
이 오류를 대응하는 방법
- 빈틈없는 테스트, 프로세스 격리, 죽은 프로세스 재시작 허용, 프로덕션 환경에서 동작 측정, 모니터링
3. 인적 오류
: 운영자의 설정 오류가 중단의 주요 원인이라 한다. (하드웨어 결함은 10~25%)
이 오류를 대응하는 방법
- 오류 가능성을 최소화할 수 있도록 설계
- 프로덕션 환경에서 데이터 분석하지 않게 샌드박스를 제공하라
- 철저하게 테스트하라
- 성능지표, 오류율을 확인할 수 있는 명확한 모니터링을 구축하라
- 조작 교육과 실습
신뢰성이 깨진다면...
: 버그로 인한 생산성 저하, 공식 자료 수치 잘못 전달 시 법적으로 위험, 매출 손실, 명성 타격
확장성
: 증가한 부하에 대처하는 시스템 능력
확장성을 논의한다는 의미는
- 시스템이 커지면 어떻게 대처해야 할까?
- 추가 부하를 다루기 휘애 계산 자원을 어떻게 투입할까?
부하 측정에 대해
: 부하 측정은 간결해야 한다. 그래야 "부하가 두 배면 얼마나 될까" 같은 부하 성장 질문에 답할 수 있다.
부하를 측정하는 종류 (load parameter, 부하 매개변수)
- 웹 서버 초당 요청 수
- DB 읽기 대 쓰기 비율
- 대화방 동시 활성 사용자 수(active user)
- 캐시 적중률
[예시] 부하에 대응한 트위터
행동 이벤트 종류
- 트윗 작성하기 (초당 최대 12,000건)
- 홈 타임라인 조회하기 (초당 30만 건)
작성한 트윗을 팔로워들의 홈 타임라인에 뜰 수 있게 하는 방법
- 1번: 작성한 트윗은 db에 넣고 팔로워가 홈타임라인 요청시 트윗 조회 쿼리로 제공
- 2번: 팔로워마다 홈 타임라인 캐시를 가지고 있음. 트윗 작성 시 각 팔로워 캐시에 삽입. 읽기 요청 결과를 캐시에 미리 담았기 때문에 저렴
→ 트윗 작성 이벤트 수가 홈 타임라인 조회 수 보다 작기 때문에 2번이 유리
하지만 2번도 단점이 있지
인플루언서는 팔로워가 3천만 명도 넘는데, 트윗 작성하면 3천 만번도 넘게 캐시 쓰기 작업이 일어나는게 굉장히 큰 부하이다
해결책은 하이브리드
팔로워 수가 많은 사용자는 1번으로, 나머지는 2번으로
성능 측정에 대해
부하가 증가할 때 필요한 정보는 성능이 얼마나 나올까이다. 성능 측정하는 방법이 필요하다
- 부하를 늘리되 시스템 자원(cpu, 메모리, 네트워크 대역폭)은 그대로 두면 성능에 얼마나 영향을 줄까?
- 부하를 늘리되 성능은 유지하려면 시스템 자원을 얼마나 늘려야 할까?
성능을 측정하는 종류
- 처리량(throughput)
- 하둡 같은 일괄 처리 시스템에서 사용
- 초당 처리 가능한 레코드 수
- 일정 크기의 데이터 집합으로 작업 수행 시 걸리는 전체 시간
- 응답 시간(response time)
- 온라인 시스템에서 사용
- 클라이언트가 요청을 보내고 받기까지의 시간
※ 응답 시간: 클라 관점에서의 시간. 요청 처리하는 실제 시간 + 네트워크 / 큐 지연 시간
지연 시간(latency): 서비스를 기다리면 휴지 상태인 시간
응답 시간 측정에 대해
응답 시간 특징
- 응답 시간은 같은 요청이라도 항상 다르기 때문에 단일 숫자가 아닌 값의 분포로 측정해야 한다.
- 가끔씩 오래걸리는 특이값(outlier) 이 있다.
- 이유: 컨텍스트 스위치, 네트워크 패킷 손실/TCP 재전송, 가비지 컬렉션, page fault(물리메모리에 데이터 없어서 가상메모리인 스왑 영역(디스크)에서 읽어옴), 서버 랙 진동
백분위(percentile)로 측정하자
- 이유: 평균값은 별로다. 실제 사용자 경험을 알 수 없기 때문이다.
- 중앙값(median)
- 가장 빠른 시간부터 느린 시간까지 정렬한 후의 중간 지점.
- ex. 중앙값이 200ms 면 반은 200보다 오래 걸리고 반은 짧게 걸린다.
- 얼마나 오랫동안 기다려야 하는지 알고 싶다면 중앙값이 좋은 지표다
- p50 이라고도 부른다.(=50분위)
- 일반적인 상위 백분위값 (=꼬리 지연 시간(tail latency))
- 95분위(p95)
- p95=1.5초면? 100개 중 95개는 1.5초 미만, 나머지 5개는 1.5초 이상 걸림
- 99분위(p99)
- 99.9분위(p99.9)
- 95분위(p95)
- 아마존 기준
- 99.9 분위로 응답 시간 요구사항을 측정한다.
- 응답 시간 0.1 초 느려지면 판매량 1% 감소, 1초 느려지면 16% 감소
- 서비스 수준 협약서(Service Level Agreement)
- 응답 시간 중앙값이 0.2 초 미만, 99분위가 1초 미만이면 정상 서비스 상태
- 서비스 제공 시간은 99.9% 이상이어야함
- 충족이 안되면 고객 환불 요구 가능
실전 백분위 테스트
- 테스트 할 때 클라에서 지속적으로 요청해야 한다. 이전 요청이 완료되길 기다리는 시간 때문에 전체적인 응답 시간이 느려질 것이기 때문이다. (=꼬리 지연 중복 (tail latency amplification))
부하에 대응하는 방법
부하가 증가해도 좋은 성능을 유지하려면?
- scale up (용량 확장, 수직 확장)
- scale out(규모 확장, 수평 확장)
아키텍처를 결정하는 요소 (자세한건 책에서 설명해줄게)
- 읽기 양, 쓰기 양, 데이터 양, 데이터 복잡도, 응답시간, 접근 패턴
- ex. 크기가 1kb 인 초당 10만건의 요청 처리하는 시스템 vs. 크기가 2GB 인 분당3 건을 처리하는 시스템은 설계가 달라야 한다.
유지보수성
: 유지보수를 최소화하고 레거시 소프트웨어를 만들지 않게끔 설계할 수 있는 원칙 3가지
운용성
: 운영팀이 운영하게 쉽게 만들라
좋은 운영팀이 하는 일
- 시스템 상태 모니터링, 좋지 않으면 빠른 복원
- 장애, 성능 저하 원인 추적
- 보안
- 문제 생길 수 있는 변경 사항 사전 차단
- 배포, 설정 관리 도구 마련
좋은 운영성이란 : 동일 반복 태스크를 쉽게 할 수 있는것
- 런타임동작, 시스템 내부에 대한 모니터링으로 가시성 제공
- 장비 하나 내려도 시스템 전체 영향 안 주도록 개별 의존성 회피
- 적절한 자기 회복, 필요하면 관리자가 수동 제어 할 수 있도록
- 예측 가능한 동작, 예기치 않은 사항 최소화
단순성
: 복잡한 건 최대한 제거 해 시스템을 이해하기 쉽게 만들기, 빠른 진행 속도 유지보수 최소화를 위해!
복잡함의 종류
- 상태 공간 급증, 모듈 간 강한 커플링, 복잡한 의존성, 일관성 없는 명명, 임시 방편 문제 해결
대응하는 방법
- 추상화를 잘 하자 (좋은 추상화는 책에서 자세하게 알려줄게)
- 고수준 프로그밍 언어 - 기계어, cpu 레지스터, 시스템 호출을 숨김
- SQL -디스크 기록, 메모리 저장, 데이터 구조, 동시 요청 해결 방법을 숨김
발전성
: 시스템 요구사항의 변화를 쉽게 할 수 있도록 하자
애자일 작업 패턴 (소규모)
- TDD, 리팩토링개발
대규모 데이터 시스템에서의 발전성은 책에서 자세히 알려줄게
정리
애플리케이션을 신뢰할 수 있고 확장 가능하며 유지보수가 쉬운 간단한 해결책은 없다.
하지만 이를 만족할 수 있도록 계속 재현되는 특정 패턴과 기술이 있다.
그게 뭔지 책에서 알려줄게
레퍼런스
데이터 중심 애플리케이션 설계 1장
'SearchDeveloper > 데이터 중심 애플리케이션 설계' 카테고리의 다른 글
[6] 파티셔닝 하는 방법, 리밸런싱 전략, 요청 라우팅 전략 (0) | 2023.07.01 |
---|---|
[5] 복제를 구성하는 방법과 동기화를 위한 노력 (0) | 2023.06.25 |
[4] 데이터를 다른 시스템에 전송하기 위한 부호화 (인코딩) 와 호환성 (0) | 2023.06.15 |
[3] DB가 데이터를 어떻게 저장하고, 질의하면 데이터를 어떻게 찾을까? (1) | 2023.05.31 |
[2] 어떤 데이터 모델을 어떤 경우에 쓰면 좋을까? (0) | 2023.05.15 |