시작하기 앞서
데이터 중심 애플리케이션 설계 책 리뷰 및 스터디가 어느덧 중반부를 넘어서서 Part2까지 진행되었다. 난이도도 높은 편이고, 하이라키가 잘 그려지지 않는 형태로 책이 구성되어있어서, 책 내용을 이해하기 쉽지 않았던 책이었다.
개인적으로는 조금 더 실용적인 방법론이 들어갔으면 좋았을 것 같은데, 이론적이고 이상적인 내용들로 구성되어있던 챕터도 있어서 아쉬운점도 많았다. (결국 잘 관리할 수 밖에 없다. 어플리케이션에서 잘 처리해야 한다 등.. 그래서 어떻게..?)
그럼에도 불구하고, 2장 데이터 모델과 질의 언어, 3장 저장소와 검색, 4장 부호화, 7장 트랜잭션과 같은 챕터들은 평소에 깊게 알지 못했던 개념들을 내재화하고 지식들을 흡수하는데 많은 도움이 되었다.
Part 3도 마저 이어서 읽어야 하나, 스터디를 위해 대기중인 서적들에 비해 우선순위가 낮다고 판단하여, 지금까지 읽은 Part 1, Part 2 의 내용을 다시한번 정리하는 시간을 가지고 Part 3 스터디 및 내용 정리는 천천히 진행하고자 한다.
목차
Total
Search
Part 1. 데이터 시스템의 기초
2장. 데이터 모델과 질의 언어
•
데이터 모델의 중요성
◦
데이터 모델을 어떻게 정의하냐에 따라 우리가 무엇을 할 수 있는지가 달라짐
•
데이터 모델의 종류
◦
관계형 모델
▪
관계로 구성되어있으며 순서가 없는 튜플의 집합
◦
문서형 모델
▪
더 나은 지역성 및 스키마의 유연성을 가진 모델
◦
그래프형 모델
▪
데이터간의 연결이 복잡한경우, 다대다 관계를 표현하기 좋은 모델
•
알아두면 좋은 개념들
◦
임피던스 불일치
◦
저장소 지역성
◦
쓰기 스키마
◦
읽기 스키마
3장. 저장소와 검색
•
저장소의 종류
◦
로그 구조 계열 저장소 엔진
◦
페이지 지향 계열 저장소 엔진
•
해시 색인
◦
키를 데이터 파일의 바이트 오프셋 형태로 맵핑하여 인메모리 해시맵에 유지
◦
범위 질의에 비효율적
•
컴팩션과 세그먼트 병합
◦
세그먼트들을 병합하여 로그에 중복된 키를 제거하고 각 키의 최신 값 유지
◦
보통 백그라운드 스레드에서 동작
•
로그 구조화 저장소
◦
SS 테이블
▪
key-value 쌍의 데이터 구조에서 key가 정렬된 문자열 테이블
◦
LSM 트리
▪
SS 테이블의 자료구조를 활용한 자료 구조
▪
구성
•
메모리 - memtable (B-Tree)
•
디스크 - SS Table
▪
백그라운드에서 SS 테이블 지속적으로 병합
▪
블룸필터
•
페이지 지향 저장소
◦
B 트리
▪
4KB 크기의 고정 크기 블록/페이지로 나눠서 한번에 하나의 페이지를 읽고/쓰는 저장소
▪
정렬된 키-값 쌍으로 유지 → 키-값 검색 및 범위 질의에 효율적
•
인덱스 저장 방식
◦
클러스터드 인덱스 - 실제 로우가 저장됨
◦
비클러스터드 인덱스 - 다른 곳에 저장된 로우를 가리키는 참조
▪
힙파일 - 실제 로우가 저장된 곳
•
고수준 저장소 엔진 구분
◦
트랜잭션 처리 최적화 (OLTP)
◦
분석 최적화 (OLAP)
•
컬럼 지향 저장소
◦
컬럼별로 모든 값을 저장. 컬럼을 개별 파일에 저장하여 질의에 사용되는 컬럼만 읽고 분서 진행
◦
컬럼 압축
•
구체화 뷰
◦
비정규화된 읽기전용 복사본
◦
원본 데이터 변경시 갱신 필요 (갱신으로 인한 쓰기 비용이 비싸 OLTP에서 자주 쓰이지 않음)
•
알아두면 좋은 개념들
◦
컴팩션과 세그먼트 병합
◦
SS 테이블
◦
LSM 트리
◦
B 트리
◦
쓰기 증폭
◦
쓰기전 로그 (WAL)
◦
구체화 뷰
◦
컬럼지향저장소
Part 2. 분산 데이터
4장. 부호화와 발전
•
하위 호환성
◦
새로운 코드 쓰기가 에전 버전의 코드가 기록한 데이터를 읽을 수 있어야 함
◦
새로운 버전의 쓰기 스키마 & 예전 버전의 읽기 스키마
•
상위 호환성
◦
예전 코드가 새로운 코드가 기록한 데이터를 읽을 수 있어야 함
◦
새로운 버전의 읽기 스키마 & 예전 버전의 쓰기 스키마
•
부호화와 복호화
◦
서로 다른 프로세스의 경우, 메모리가 공유되지 않으므로 인메모리 표현 → 바이트열 변환 필요
◦
부호화: 인메모리 표현 → 바이트열
◦
복호화: 바이트열 → 인메모리표현
•
부호화 형식
◦
프로그래밍 언어에 특화된 부호화
◦
텍스트 형식
▪
JSON, XML, CSV
◦
이진스키마 기반 형식 (이진 부호화)
▪
스리프트, 프로토콜버퍼, 아브로
•
데이터플로
◦
데이터베이스 레벨
▪
데이터베이스 기록 프로세스 (부호화)
▪
데이터베이스 조회 프로세스 (복호화)
◦
서비스 레벨 (RPC, REST)
▪
클라이언트(요청 부호화)
▪
서버 (요청 복호화, 응답 부호화)
▪
클라이언트 (응답 복호화)
◦
메세지 전달
▪
송신자/Producer (메세지 부호화)
▪
수신자/Consumer (메세지 복호화)
•
알아두면 좋은 개념들
◦
상위/하위 호환성
◦
부호화/복호화
◦
위치 투명성
◦
멱등성
◦
액터모델
5장. 복제
•
복제의 목적
◦
고가용성, 내결함성
◦
지연시간 감소
◦
확장성 증가
•
단일 리더 기반 복제
◦
형태
▪
쓰기 - 리더 / 읽기 - 팔로워
◦
비동기식 복제
▪
복제 지연
▪
최종적 일관성
◦
복제 로그
▪
복제 로그를 바탕으로 마스터와의 차이를 처리
◦
스플릿 브레인
▪
새로운 리더 선정시 발생할 수 있는 이슈 (합의)
◦
복제 방식
▪
구문 기반 복제
▪
쓰기전 로그 배송
▪
논리적 (로우기반) 로그 복제
•
다중 리더 기반 복제
◦
내결함성 높음
◦
이슈
▪
쓰기 충돌 - LWW (최종 쓰기 승리)
▪
AI, 무결성 제약
•
리더 없는 복제
◦
아마존 다이나모 시스템
◦
읽기 복구 / 안티 엔트로피 처리
◦
정족수
▪
w + r > n
•
복제 지연 이상 현상
◦
쓰기 후 읽기 일관성
▪
자신이 쓴 글이 아직 동기화 되지 않은 상태에서 팔로워를 통해서 읽기를 시도 하는 경우
▪
쓰기 후 읽기 일관성을 보장해야함
▪
쓰는 액션에 대해서는 리더로 관리
◦
단조 읽기
▪
리더로부터의 데이터 동기화가 다 되지 않은 상태에서, 클라이언트가 동기화가 된 팔로워로부터 읽기를 시도 한 후, 동기화가 되지 않은 팔로워로부터 같은 데이터에 대해 읽기를 시도하는 경우
▪
단조 읽기 방법으로는 사용자 ID 를 해시화 하여 이를 기반으로 복제 서버를 선택해야한다.
▪
사용자가 어떤 시점에 데이터를 본 후에는 예전 시점의 데이터는 나중에 볼 수 없음
◦
일관된 순서로 읽기
▪
리더로부터 데이터 동기화가 지연이 발생하여 순서대로 동기화가 안된 경우 데이터 조회시 순서가 맞지 않는 경우
▪
일관된 순서로 읽기 보장을 해야함
▪
서로 인과성이 있는 쓰기가 동일한 파티션에 기록 되게끔 해야함
•
쓰기 충돌
◦
다중 리더 복제, 리더 없는 복제 동시성 문제
◦
해결 알고리즘
▪
LWW
▪
이전 발생 관계 결정 알고리즘
6장. 파티셔닝
•
파티셔닝 목적
◦
저장하고 처리할 데이터가 너무 많아 장비 1대로 처리 불가능할 경우 사용
◦
핫스팟을 생기지 않게하고 데이터와 질의 부하를 여러 장비에 균등 분배
•
파티셔닝 기법
◦
키 범위 파티셔닝
▪
키를 raw 하게 범위형태로 사용하는 것, 예) 알파벳(A-Z)
▪
특정 키에 몰릴 수 있음 (핫스팟)
◦
해시 파티셔닝
•
파티셔닝과 보조 색인
◦
파티셔닝은 키-값 데이터 모델에 기본적으로 의존 (기본키만 적용)
◦
보조색인은 파티션에 깔끔하게 대응되지 않는 이슈 있음
◦
보조 색인 파티셔닝 방법
▪
문서 파티셔닝 색인
•
파티션 별로 저장
•
지역 색인
•
스캐터/게더
▪
용어 파티셔닝 색인
•
용어에 따라 파티션을 정해서 나눠서 저장
•
전역 색인
•
리밸런싱 전략
◦
해쉬값 mod N
◦
파티션 개수 고정
◦
동적 파티셔닝
▪
키 범위 파티셔닝 단점 보완
◦
노드 비례 파티셔닝
•
서비스 디스커버리
◦
데이터베이스의 경우 노드-파티셔닝의 리밸런싱에 따른 IP, PORT 등을 찾는 문제
◦
이를 해결하기 위해 코디네이션 서비스 존재
▪
클러스터 메타 데이터 추적
7장. 트랜잭션
•
ACID
◦
원자성 (Atomicity)
◦
일관성 (Consistency)
◦
격리성 (Isolation)
◦
지속성 (Durability)
•
격리 수준
◦
read commited (커밋 후 읽기)
▪
더티 읽기, 더티 쓰기 방지
▪
읽기 스큐 현상 발생 가능
◦
repetable read (스냅샷 격리)
▪
다중 동시성 제어 (MVCC)
▪
팬텀 읽기 발생 가능
◦
직렬성 격리
▪
실제적 직렬성 구현
▪
2PL
▪
serializable (직렬성 스냅샷 격리, SSI)
•
오래된 MVCC 읽기 감지하기 - 읽기 전 커밋되지 않은 쓰기 확인
◦
커밋 시 디비에 무시된 쓰기중 커밋된 게 있다면 확인
◦
커밋된게 있다면 트랜잭션 어보트해야함
•
과거의 읽기에 영향을 미치는 쓰기 감지하기 - 읽은 후에 다른 트랜잭션이 그 데이터를 변경할 때
◦
트랜잭션이 디비에 쓸때 영향받는 데이터를 최근에 읽은 트랜잭션이 있는지 색인에서 확인
◦
충돌되는 쓰기가 존재할 경우 어보트 진행
•
경쟁 조건 이상 현상
◦
더티 읽기 - 커밋되지 않은 데이터 읽기
◦
더티 쓰기 - 커밋되지 않은 데이터 쓰기
◦
읽기 스큐
▪
다른 시점에 다른 데이터 보기 → MVCC로 해결 가능
▪
이전과 다른 결과가 나타나는 현상
▪
쓰기 트랜잭션이 실행되는 와중에 읽기 트랜잭션이 실행되서 결과물이 다르게 보이는 것
◦
쓰기 스큐
▪
트랜잭션이 무언가를 읽고, 읽은 값 기반으로 어떤 결정을 하여 데이터베이스를 씀.
▪
예) 신규 user 생성시 타이밍 이슈로 동일한 정보의 user 가 2개 record 로 생성 되는 경우
•
DB 엔진 상의 버그는 아니나 비즈니스 적으로 문제가 되는 상황
▪
직렬성 격리으로만 해결 가능
◦
갱신 손실
▪
두 클라이언트가 동시에 read-modify-write 주기 실행
▪
두 트랜잭션이 한개의 객체를 갱신
▪
방지 기법
•
원자적 쓰기 연산
•
명시적 잠금 (select for update)
•
자동 감지
•
Compare and set
◦
팬텀 읽기
▪
읽기 트랜잭션이 실행되는 와중에 쓰기 트랜잭션에 영향을 받아서 유령이 생긴 것
▪
예) 10명 읽는 와중에 1개 record 가 추가 되서 11개가 된 것
8장. 분산 시스템의 골칫거리
•
비동기 패킷 네트워크 (분산 시스템)
◦
노드간에 패킷(메시지) 전송하여 네트워크를 통해 통신
◦
메세지가 언제 도착할지, 전송했는지, 도착했는지 알 수 없음
▪
기약없는 지연
◦
다양한 이유로 응답을 못 받을 수 있음
◦
비공유 시스템
◦
타임아웃을 통해 일반적으로 문제 대응
•
분산 시스템에서 일어날 수 있는 문제
◦
부분 장애
▪
패킷이 손실 또는 임의로 지연 가능 (응답 또한 손실 & 지연 가능)
▪
타임아웃을 통해 해결
▪
적정 타임아웃 시간 → 정답 없음. 실험을 통해 지속적인 조정 필요
◦
신뢰성 없는 시계
▪
시간이 안맞을 수 있음
▪
시계에 의존하는 것은 위험
◦
프로세스 중단 발생 가능
▪
프로세스가 중간에 멈추는 경우, 죽지 않았음에도 죽었다고 인식될 수 있음
•
분산 시스템의 특징
◦
부분 장애 / 부분 살패
◦
구성요소의 일부가 고장나더라도 전체로서 시스템은 계속 동작할 수 있도록 부분 실패 내성을 지닐 수있도록 노력 필요 (소프트웨어의 내결함성 메커니즘 적용)
•
알아두면 좋은 개념들
◦
펜싱 토큰
▪
단조 증가
▪
잠금이나 임차권을 승인할 때마다 증가되는 숫자
▪
클라이언트 쓰기 요청이 자신의 현재 펜싱 토큰을 포함하도록 요구 가능
▪
주키퍼
•
트랜잭션 ID zxid, 노드버전 cversion
◦
비잔틴 결함
▪
어떤 노드가 실제로는 받지 않은 특정 메시지를 받았다고 주장하는 상황
▪
비잔틴 내결함성 알고리즘을 적용하여 시스템이 올바르게 동작하게 해야함
9장. 일관성과 합의
•
일관성 모델
◦
강한 일관성 모델
▪
선형성 모델
•
모든 데이터가 선으로 이어져있고 모든 연산이 원자적으로 보이는 것
•
이해하기 쉬우나 느림
▪
전체 순서, 최신성 보장
◦
약한 일관성 모델
▪
인과성 모델
▪
부분 순서
◦
선형성이 중요한 것이 아니라 인과적 일관성이 중요함
▪
선형성 > 인과성
▪
인과 관계에 일관성이 있어야한다
•
CAP 정리
◦
종류
▪
일관성 (Consistency)
▪
가용성 (Availability)
▪
분단 내성 (Partition tolerance)
◦
선형성(일관성) O → 가용성 X
◦
가용성 O → 선형성(일관성) X
◦
네트워크 분단이 발생했을 때 일관성과 가용성중 하나를 선택하라는 의미
•
램포드 타임스탬프
◦
인과성에 일관적인 일련번호를 생성하는 방법
◦
전체 순서화를 제공
▪
(카운터, 노드 ID)
▪
카운터가 큰 것이 타임스탬프가 크고, 카운터 값이 같으면 노드 ID 가 큰것이 타임스탬프가 큼
◦
노드별로 모든 데이터를 갖고와서 순서를 정해야하므로 다소 느리고 어려움
•
전체 순서 브로드캐스트
◦
분산 시스템에서는 모든 노드에서 연산의 전체 순서가 동일하도록 합의하기가 어려우므로 이 문제를 해결하기 위해 사용
◦
전체 순서 브로드 캐스트는 비동기식
◦
언제 올지 모를 뿐, 고정된 순서로 받음
◦
주키퍼, etcd
◦
다른 노드에 전부다 데이터를 브로드캐스팅함으로써, 인과성과 순서 보장
•
합의
◦
여러 노드들이 뭔가에 동의하게 만드는 것
◦
예시) 리더 선출 / 원자적 커밋
◦
2단계 커밋 (2PC)
▪
여러 노드에 걸친 원자적 트랜잭션 커밋을 달성하는, 즉 모든 노드가 커밋되거나 모든 노드가 어보트 되도록 보장하는 알고리즘
◦
합의로 해결 가능한 문제들
▪
선형성 comapre-and-set 레지스터
▪
원자적 트랜잭션 커밋
▪
전체 순서 브로드캐스트
▪
잠금과 임차권
▪
멤버십/코디네이터 서비스
▪
유일성 제약 조건
◦
위 문제들을 결정할 수 있는 능력을 한 노드에게만 주면 간단. 그러나 단일 리더 장애 발생 시 내결함성 크게 저하
◦
해결 방법
▪
리더가 복구될때까지 대기
▪
수동으로 새로운 노드 선택 후 장애 복구
▪
자동으로 새 리더 선택 알고리즘
•
코디네이션 서비스
◦
합의, 장애감지, 멤버십 서비스를 위탁하는 중요한 역할 수행
◦
장애감지와 합의를 연결 → 어떤 노드가 살아있고 죽었는지 동의할 수 있음