가상 면접 사례로 배우는 대규모 시스템 설계 기초 | 알렉스 쉬 - 교보문고
가상 면접 사례로 배우는 대규모 시스템 설계 기초 | 페이스북의 뉴스 피드나 메신저,유튜브, 구글 드라이브 같은 대규모 시스템은 어떻게 설계할까? IT 경력자라도 느닷없이 대규모 시스템을 설
product.kyobobook.co.kr
6장, 키-값 저장소 설계
- 키-값 저장소 (Key-Value Store)는 키-값 데이터베이스라고도 불리는 비관계형 데이터베이스이다.
- 이 저장소에 저장되는 값은 고유 식별자를 키로 가져야 한다.
- 키와 값 사이의 이런 연결 관계를 ‘키-값’ 쌍 (Pair)이라 지칭한다.
- 키-값 쌍에서의 키는 유일해야 하며 해당 키에 매달린 값은 키를 통해서만 접근할 수 있다.
- 키는 일반 텍스트일 수도 있고 해시 값일 수도 있다.
- 성능 상의 이유로, 키는 짧을수록 좋다.
- ex) 일반 텍스트 키 : “last_logged_in_at”
- ex) 해시 키 : 253DDEC4
- 키-값 쌍에서의 값은 문자열일 수도 있고 리스트일 수도 있고 객체일 수도 있다.
- 키-값 저장소는 보통 값으로 무엇이 오든 상관하지 않는다.
- 대표적 예로 Amazon DynamoDB, Memcached, Redis 등이 있다.
- 단일 서버 키-값 저장소
- 한 대 서버만 사용하는 키-값 저장소를 설계하는 것은 쉽다.
- 가장 직관적인 방법은 키-값 쌍 전부를 메모리에 해시 테이블로 저장하는 것
- 이 접근법은 빠른 속도를 보장하긴 하나 모든 데이터를 메모리 안에 두는 것이 불가능할 수도 있다는 약점을 가진다.
- 개선책
- 데이터 압축 (Compression)
- 자주 쓰이는 데이터만 메모리에 두고 나머지는 디스크에 저장
- 그러나 이렇게 개선한다고 해도, 한 대 서버로 부족한 때가 곧 찾아온다.
- 많은 데이터를 저장하려면 분산-키 값 저장소(Distributed Key-Value Store)를 만들 필요가 있다.
- 개선책
- 분산 키-값 저장소
- 분산 해시 테이블이라고도 불림
- 키-값 쌍을 여러 서버에 분산
- CAP 정리 (Consistency, Availability, Partition Tolerance Theorem)을 이해하고 있어야 함
- 세 가지 요구사항을 동시에 만족하는 분산 시스템을 설계하는 것은 불가능하다는 정리
- 데이터 일관성 (Consistency)
- 어떤 노드에 접속했느냐에 관계 없이 언제나 같은 데이터를 보게 되어야 한다.
- 가용성 (Availability)
- 일부 노드에 장애가 발생하더라도 항상 응답을 받을 수 있어야 한다.
- 파티션 감내 (Parition Tolerance)
- 파티션은 두 노드 사이에 통신 장애가 발생하였음을 의미
- 네트워크에 파티션이 생기더라도 시스템은 계속 동작하여야 한다는 의미
- 데이터 일관성 (Consistency)
- 키-값 저장소는 세 가지 요구사항 가운데 어느 두 가지를 만족하냐에 따라 다음과 같이 분류할 수 있다.
- CP 시스템
- 일관성과 파티션 감내를 지원하는 키-값 저장소, 가용성을 희생
- AP 시스템
- 가용성과 파티션 감내를 지원하는 키-값 저장소, 데이터 일관성을 희생
- CA 시스템
- 일관성과 가용성을 지원하는 키-값 저장소, 파티션 감내를 희생
- 그러나 통상 네트워크 장애는 피할 수 없는 일로 여겨지므로, 분산 시스템은 반드시 파티션 문제를 감내할 수 있도록 설계되어야 한다.
- 따라서 실세계에 CA 시스템은 존재하지 않는다.
- CP 시스템
- 다양한 상태의 분산 시스템
- 이상적 상태
- 네트워크가 파티션되는 상황은 일어나지 않는다. (P 만족)
- 어떤 단일 저장소에 기록된 내용은 자동적으로 모든 분산 서비스 내 저장소로 복제된다.
- 데이터 일관성과 가용성도 만족된다. (C, A 만족)
- 실세계 분산 시스템
- 분산 시스템은 파티션 문제를 피할 수 없기에, 일관성과 가용성 사이에서 하나를 선택해야 한다.
- 일관성을 선택한 경우 (CP 시스템)
- 분산 서버 사이에 생길 수 있는 데이터 불일치 문제를 피하기 위해 장애가 발생하지 않은 서버에 쓰기 연산을 중단시켜야 하는데, 그렇게 하면 가용성이 깨진다.
- 은행권 시스템은 보통 데이터 일관성을 양보하지 않는다.
- 온라인 뱅킹 시스템이 계좌 최신 정보를 출력하지 못하면 큰 문제
- 네트워크 파티션 때문에 일관성이 깨질 수 있는 상황이 발생한다면 이런 시스템은 상황이 해결될 때 까지 오류를 반환해야 한다.
- 가용성을 선택한 경우 (AP 시스템)
- 낡은 데이터를 반환할 위험이 있더라도 계속 쓰기 연산을 허용
- 파티션 문제가 해결된 뒤에 새 데이터를 복구된 오류 발생 서버에 전송
- 이상적 상태
- 분산 키-값 저장소를 만들 때는 그 요구사항에 맞도록 CAP 정리를 적용해야 한다.
- 세 가지 요구사항을 동시에 만족하는 분산 시스템을 설계하는 것은 불가능하다는 정리
- 데이터 파티션
- 대규모 애플리케이션의 경우 전체 데이터를 한 대 서버에 몰아넣는 것은 불가능
- 가장 단순한 해결책은 데이터를 작은 파티션들로 분할한 다음 여러 대 서버에 저장하는 것
- 데이터를 파티션 단위로 나눌 때는 다음 문제를 중요하게 따져봐야 한다.
- 데이터를 여러 서버에 고르게 분산할 수 있는가
- 노드가 추가되거나 삭제될 때 데이터의 이동을 최소화할 수 있는가
- 안정 해시를 통해 위 문제를 적절히 해결할 수 있다.
- 일관성 모델 (Consistency Model)
- 데이터 일관성 수준을 결정하는 방법으로, 종류가 다양하다
- 강한 일관성 (Strong Consistency)
- 모든 읽기 연산은 가장 최근에 갱신된 결과를 반환
- 클라이언트는 절대 낡은 (Out-Of-Date) 데이터를 보지 못함
- 모든 사본에 현재 쓰기 연산의 결과가 반영될 때 까지 해당 데이터에 대한 읽기/쓰기를 금지
- 새로운 요청의 처리가 중단되기에 고가용성 시스템에 적합하지 않다.
- 약한 일관성 (Weak Consistency)
- 읽기 연산은 가장 최근에 갱신된 결과를 반환하지 못할 수 있음
- 최종 일관성 (Eventual Consistency)
- 약한 일관성의 한 형태로, 갱신 결과가 결국에는 모든 사본에 반영(동기화)되는 모델
- 다이나모 또는 카산드라 같은 저장소에서 채택한 모델
- 쓰기 연산이 병렬적으로 발생하면 시스템에 저장된 값의 일관성이 깨질 수 있는데, 이 문제는 클라이언트가 해결해야 한다.
- 클라이언트 측에서 데이터의 버전 정보를 활용해 일관성이 깨진 데이터를 읽지 않도록 하는 기법
- 비 일관성 해소 기법 : 데이터 버저닝
- 데이터를 다중화하면 가용성은 높아지지만 사본 간 일관성이 깨질 가능성이 높다.
- 버저닝과 벡터 시계는 그 문제를 해소하기 위해 등장한 기술
- 버저닝 (Versioning)
- 데이터를 변경할 때 마다 해당 데이터의 새로운 버전을 만드는 것
- 각 버전의 데이터는 변경 불가능 (immutable)
- 벡터 시계 (Vector Clock)
- 충돌을 발견하고 자동으로 해결해 낼 버저닝 시스템
- 어떤 버전 X가 어떤 버전 Y의 이전 버전인지 (따라서 충돌이 없는지) 쉽게 판단할 수 있음
- 버전 Y에 포함된 모든 구성요소의 값이 X에 포함된 모든 구성요소 값보다 같거나 큰지만 보면 됨
- 단점
- 충돌 감지 및 해소 로직이 클라이언트에 들어가야 하므로, 클라이언트 구현이 복잡해진다.
- [서버: 버전]의 순서쌍 개수가 굉장히 빨리 늘어난다. 이를 해결하기 위해 길이에 어떤 임계치를 설정하고, 임계치 이상으로 길이가 길어지면 오래된 순서쌍을 벡터 시계에서 제거하도록 해야 함
- 그러나 오래된 순서쌍을 벡터 시계에서 제거한다면 버전 간 선후 관계가 정확하게 결정될 수 없기 때문에 충돌 해소 과정의 효율성이 낮아지게 된다.
- 하지만 다이나모 데이터베이스 문헌에 따르면 아마존은 실제 서비스에서 위와 같은 문제가 벌어지는 것을 발견한 적이 없다고 공표하였으며, 대부분의 기업에서 벡터 시계는 적용해도 괜찮은 솔루션으로 평가됨
- 장애 처리
- 장애는 불가피하기만 한 것이 아닌 흔하게 벌어지는 사건
- 장애를 어떻게 처리할 것이냐 하는 것은 굉장히 중요한 문제
- 장애 감지 (Failure Detection)
- 분산 시스템에서는 그저 한 대 서버가 “지금 서버 A가 죽었습니다.” 라고 한다고 해서 바로 서버 A를 장애처리 하지는 않는다.
- 보통 두 대이상의 서버가 똑같이 서버 A의 장애를 보고해야 해당 서버에 실제 장애가 발생했다고 간주한다.
- 모든 노드 사이에 멀티캐스팅 (Multicasting) 채널을 구축하는 것이 서버 장애를 감지하는 가장 손쉬운 방법이나, 서비스가 많을 때 비효율적
- 가십 프로토콜 (Gossip Protocol) 같은 분산형 장애 감지 (Decentralized Failure Detection) 솔루션을 채택하는 편이 효율적
- 강한 일관성 (Strong Consistency)
- 데이터 일관성 수준을 결정하는 방법으로, 종류가 다양하다
- 느낀 점
- Key-Value DB의 종류와 그 내부 로직들을 더 깊이 있게 배울 수 있었다.
- CAP 정리에 대해 대략적으로만 알고 있었는데, 이번 기회에 정확히 CAP가 무엇인지, 어떤 구분을 가지는지 파악할 수 있었다.
- 오류 없는 완전한 시스템이란 없다. 오류에 적절히 대처하고, 빠르게 대처하고, 더 나은 대처를 할 수 있는 방안을 계속해서 강구하는 것이 올바른 개발자의 자세겠다.
'개발 이야기 (Dev Story)' 카테고리의 다른 글
"가상 면접 사례로 배우는 대규모 시스템 설계 기초"를 읽고 - 10장 (2) | 2024.05.11 |
---|---|
"가상 면접 사례로 배우는 대규모 시스템 설계 기초"를 읽고 - 7장 (0) | 2024.05.11 |
"가상 면접 사례로 배우는 대규모 시스템 설계 기초"를 읽고 - 4장 (0) | 2024.05.11 |
[아키텍처 패턴] 레이어 패턴 (Layered Pattern) (0) | 2024.05.10 |
"가상 면접 사례로 배우는 대규모 시스템 설계 기초"를 읽고 - 3장 (0) | 2024.05.10 |