단일 서버 키-값 저장소분산 키-값 저장소CAP 정리실세계의 분산 시스템시스템 컴포넌트데이터 파티션데이터 다중화데이터 일관성일관성 모델비 일관성 해소 기법: 데이터 버저닝장애 처리데이터 센터 장애 처리
단일 서버 키-값 저장소
- 한 대 서버만 사용하는 키-값 저장소를 설계하는 것은 쉽다. 가장 직관적인 방법은 키-값 쌍 전부를 메모리에 해시 테이블로 저장하는 것이다.
- 그러나 이 접근법은 빠른 속도를 보장하긴 하지만 모든 데이터를 메모리 안에 두는 것이 불가능 할 수도 있다는 약점을 갖고 있다.
- 개선책
- 데이터 압축(compression)
- 자주 쓰이는 데이터만 메모리에 두고 나머지는 디스크에 저장
- 이렇게 개선한다 해도, 한 대 서버로는 부족한 때가 찾아온다. 많은 데이터를 저장하려면 분산 키-값 저장소를 만들 필요가 있다
분산 키-값 저장소
CAP 정리
데이터 일관성(consistency), 가용성(availability), 파티션 감내(partition tolerance)라는 세 가지 요구사항을 동시에 만족하는 분산 시스템을 설계하는 것은 불가능 하다는 것
- 데이터 일관성 : 분산 시스템에 접속하는 모든 클라이언트는 어떤 노드에 접속했느냐에 관계없이 언제나 같은 데이터를 보게 되어야 함
- 가용성 : 분산 시스템에 접속하는 클라이언트는 일부 노드에 장애가 발생하더라도 항상 응답을 받을 수 있어야 한다.
- 파티션 감내 : 파티션은 두 노드 사이에 통신 장애가 발생하였음을 의미한다. 파티션 감내는 네트워크에 파티션이 생기더라도 시스템은 계속 동작하여야 한다는 것을 뜻함
이들 가운데 어떤 두 가지를 충족하려면, 나머지 하나는 희생되어야 함
실세계의 분산 시스템
- 분산 시스템은 파티션 문제를 피할 수 없다. 그리고 파티션 문제가 발생하면 우리는 일관성과 가용성 사이에서 하나를 선택해야 한다.
- 만약 n1, n2, n3 의 노드가 있고 n3에 장애가 발생하여 n1 및 n2 와 통신할 수 없는 상황이라면 클라이언트가 n1, n2에 기록한 데이터는 n3 에 전달되지 않음. n3 에 기록되었으나 n1 과 n2 로 전달되지 않은 데이터가 있다면 n1과 n2는 오래된 사본을 갖고 있을 것
- 가용성 대신 일관성을 선택하면(CP 시스템): 세 서버 사이에 데이터 불일치 피하기 위해 n1과 n2에 쓰기 연산을 중단시켜야 함 → 가용성 x
- 은행권 시스템은 보통 데이터 일관성을 양보하지 않음. 가용성이 없더라도 계속 데이터 일관성을 유지해야함
- 일관성 대신 가용성 선택(AP 시스템) : 낡은 데이터를 반환할 위험이 있더라도 계속 읽기 연산을 허용해야 함
- 또한 n1 과 n2 는 계속 쓰기 연산 허용, 파티션 문제가 해결되면 새 데이터를 n3에 전송
시스템 컴포넌트
데이터 파티션
대규모 애플리케이션의 경우 전체 데이터를 한 대 서버에 욱여넣는 것은 불가능 하다.
가장 단순한 해결책은 데이터를 작은 파티션들로 분할한 다음 여러 대 서버에 저장하는 것이다.
데이터를 파티션 단위로 나눌 때는 다음 두 가지 문제를 중요하게 따져봐야 한다.
- 데이터를 여러 서버에 고르게 분산할 수 있는가
- 노드가 추가되거나 삭제될 때 데이터의 이동을 최소화할 수 있는가
⇒ 안정 해시
- 장점
- 규모 확장 자동화 : 시스템 부하에 따라 서버가 자동으로 추가되거나 삭제될 수 있음
- 다양성 : 각 서버의 용량에 맞게 가상 노드의 수를 조정할 수 있다. 즉, 고성능 서버는 더 많은 가상 노드를 가질 수 있음
데이터 다중화
- 높은 가용성과 안전성을 확보하기 위해서는 데이터를 N개 서버에 비동기적으로 다중화할 필요가 있음
- 같은 데이터 센터에 속한 노드는 정전, 네트워크 이슈, 자연재해 등의 문제를 동시에 겪을 가능성이 있기에 안정성을 담보하기 위해 데이터의 사본은 다른 센터의 서버에 보관하고, 센터들은 고속 네트워크로 연결한다.
데이터 일관성
여러 노드에 다중화된 데이터는 적절히 동기화가 되어야 한다.
정족수 합의 프로토콜(Quorum Consensus)을 사용하면 읽기/쓰기 연산 모두에 일관성을 보장할 수 있다
정의
N = 사본수 개수
W = 쓰기 연산에 대한 정족수. 쓰기 연산이 성공한 것으로 간주되려면 적어도 W개의 서버로부터 쓰기 연산이 성공했다는 응답을 받아야 한다.
R = 읽기 연산에 대한 정족수. 읽기 연산이 성공한 것으로 간주되려면 적어도 R개의 서버로부터 응답을 받아야 한다.
- W, R, N의 값을 정하는 것은 응답 지연과 데이터 일관성 사이의 타협점을 찾는 전형적인 과정이다.
- 가능한 몇가지 구성
- R=1, W=N : 빠른 읽기 연산에 최적화된 시스템
- W=1, R=N: 빠른 쓰기 연산에 최적화된 시스템
- W+R > N : 강한 일관성이 보장됨(보통 N=3, W=R=2)
- W+R ≤ N : 강한 일관성이 보장되지 않음
W+R > N 인 경우에는 강한 일관성이 보장된다. 일관성을 보증할 최신 데이터를 가진 노드가 최소 하나는 겹칠 것이기 때문이다.
일관성 모델
강한 일관성 : 모든읽기 연산은 가장 최근에 갱신된 결과를 반환한다. 다시 말해 클라이언트는 절대로 낡은(out-of-date) 데이터를 보지 못한다.
약한 일관성 : 읽기 연산은 가장 최근에 갱신된 결과를 반환하지 못할 수 있다.
결과적 일관성 : 약한 일관성의 한 형태로, 갱신 결과가 결국에는 모든 사본에 반영(즉, 동기화)되는 모델이다.
- 강한 일관성을 달성하는 일반적인 방법은, 모든 사본에 현재 쓰기 연산의 결과가 반영될 때까지 해당 데이터에 대한 읽기/쓰기를 금지하는 것이다. 이 방법은 고가용성 시스템에는 적합하지 않다.
비 일관성 해소 기법: 데이터 버저닝
데이터를 다중화하면 가용성은 높아지지만 사본 간 일관성이 깨질 가능성은 높아진다.
버저닝(versioning)과 벡터 시계(vector clock)는 그 문제를 해소하기 위해 등장한 기술이다.
벡터 시계는 [서버, 버전]의 순서쌍을 데이터에 매단 것이다. 어떤 버전이 선행 버전인지, 후행 버전인지, 아니면 다른 버전과 충돌이 있는지 판별하는데 쓰인다.
벡터 시계의 단점
- 충돌 감지 및 해소 로직이 클라이언트에 들어가야 하므로, 클라이언트 구현이 복잡해짐
- [서버:버전]의 순서쌍 개수가 굉장히 빨리 늘어남
장애 처리
장애 감지
모든 노드 사이에 멀티캐스팅 채널을 구축하는 것이 서버 장애를 감지하는 가장 손쉬운 방법이다. 하지만 이 방법은 서버가 많을 때는 분명 비효율적이다.
가십 프로토콜 같은 분산형 장애 감지 솔루션을 채택하는 편이 보다 효율적임
가십 프로토콜의 동작 원리
- 각 노드는 멤버십 목록을 유지. 멤버십 목록은 각 멤버 ID와 그 박동 카운터 쌍의 목록
- 각 노드는 주기적으로 자신의 박동 카운터를 증가시킨다.
- 각 노드는 무작위로 선정된 노드들에게 주기적으로 자기 박동 카운터 목록을 보낸다.
- 박동 카운터 목록을 받은 노드는 멤버십 목록을 최신 값으로 갱신
- 어떤 멤버의 박동 카운터 값이 지정된 시간 동안 갱신되지 않으면 해당 멤버는 장애 상태인 것으로 간주
일시적 장애 처리
- 네트워크나 서버 문제로 장애 상태인 서버로 가는 요청은 다른 서버가 잠시 맡아 처리. 그동안 발생한 변경사항은 해당 서버가 복구 되었을 때 일괄 반영하여 데이터 일관성을 보존
- 이를 위해 임시로 쓰기 연산을 처리한 서버에는 그에 관한 단서(hint) 를 남겨두는데 이런 장애 처리방안을 단서 후 임시 위탁(hinted handoff) 기법이라 부름
- 장애 상태인 노드 s2에 대한 읽기 및 쓰기 연산은 일시적으로 노드 s3가 처리하고, s2가 복구되면, s3은 갱신된 데이터를 s2로 인계함
영구 장애 처리
hinted handoff는 일시적 장애를 처리하기 위한 것
영구적인 노드의 장애 상태는 anti-entropy 프로토콜을 구현하여 사본들을 동기화 함
반 엔트로피 프로토콜은 사본들을 비교하여 최신 버전으로 갱신하는 과정을 포함하는데, 사본 간의 일관성이 망가진 상태를 탐지하고 전송 데이터의 양을 줄이기 위해 Merkle 트리를 사용한다.
데이터 센터 장애 처리
데이터 센터 장애는 정전, 네트워크 장애, 자연재해 등 다양한 이유로 발생할 수 있다.
데이터 센터 장애에 대응할 수 있는 시스템을 만들려면 데이터를 여러 데이터 센터에 다중화하는 것이 중요하다.
한 데이터센터가 완전히 망가져도 사용자는 다른 데이터 센터에 보관된 데이터를 이용할 수 있을 것이다.