가용성과 일관성, 확장성 유지하기 - 대규모 시스템 설계 기초 6장 (2)

Broccolism·2022년 10월 1일
1

표지

가상 면접 사례로 배우는 대규모 시스템 설계 기초

6장. 분산 키-값 저장소 설계

분산 키-값 저장소 구현을 위한 핵심 기술 몇가지

어떤걸 고려해야 할까? 어떤 기술을 쓰면 좋을까?

데이터 파티셔닝과 다중화

데이터 파티셔닝

파티셔닝은 하나의 큰 데이터를 조각내어 분산시켜 저장하는 기법이다. 아래 2가지 문제를 잘 따져봐야 한다.

  • 데이터를 어떻게 고르게 분산시킬 것인가
    • 예) 핫스팟 키 문제: 소셜 네트워크 앱에서 저스틴 비버, 레이디 가가 등 팔로워가 엄청나게 많은 사람들의 데이터가 한 서버에 모두 몰려있다면 데이터를 분산 시킨 의미가 없을 것이다.
  • 노드가 추가/삭제 될 때 어떻게 데이터 이동을 최소화 할 것인가
    • 트래픽에 따라 서버가 유동적으로 증설/삭제되어야 효과적으로 요청을 처리할 수 있을 것이다. 그런데 이런 변화가 있을 때마다 수많은 데이터가 이동해야 한다면 오히려 딜레이가 더 생길 수 있다.

이 문제에 대한 해답은 안정 해시 설계에서 찾을 수 있다. 위 2가지 요구사항을 정확히 잘 수행하는 기법이다. 추가로 이런 장점도 갖는다.

  • 다양성 heterogeneity: 각 서버의 용량에 맞게 가상 노드의 수를 조정할 수 있다. 즉, 고성능 서버는 더 많은 데이터를 많이 저장할 수 있다.

데이터 다중화

다중화는 (주로) 비동기적으로 복사본을 저장, 즉 백업하는 것이다. 높은 가용성과 안정성을 확보하기 위해서 다중화가 필요하다.

안정 해시

어떤 데이터를 어디에 저장할 것인지 결정 할 때도 안정 해시 기법을 사용할 수 있다. 키 하나를 해시 링 위에 배치한 후, 그 지점으로부터 시계 방향으로 링을 순회하면서 만나는 첫 N개 서버에 사본을 보관하면 된다. 위 그림은 사본을 3개 저장하려고 할 때, Key1의 사본이 S1, S2, S3에 저장되는 모습을 보여준다. 이 때 주의할 점은 다음과 같다.

  • 만약 가상 노드를 사용한다면, 선택한 노드 개수가 실제 물리 서버 개수보다 많아질 수 있다.
    • 이를 피하기 위해서는 같은 물리 서버를 중복 선택하지 않도록 해야 한다.
  • 같은 데이터 센터에 속한 노드는 정전, 네트워크 이슈, 자연재해 등을 동시에 겪을 가능성이 있다.
    • 따라서 데이터의 사본은 서로 다른 센터의 서버에 보관하는게 좋다.

일관성과 불일치 해소

여기서 말하는 일관성은 ‘여러 노드에 다중화된 데이터를 동기화하여 유지되는 일관성, 즉 원본 데이터의 사본이 서로 같은 값을 가진 상태로 잘 분산되어 저장되어있는 성질’을 의미한다. 동기화가 제대로 되지 않으면 일관성이 깨진다.

이를 막기 위한 여러가지 방법이 있는데, 책에서는 정족수 합의(Quorum Consensus) 프로토콜을 소개한다. 한마디로 요약하자면 다수결의 원칙을 따르는 것이다. 정족수는 그 다수결을 위한 기준이 되는 노드의 개수다.

  • N: 사본의 개수.
  • W: 쓰기 연산에 대한 정족수. W개 이상 서버로부터 쓰기 연산이 성공했다는 응답을 받았으면 해당 연산은 성공한 것으로 간주한다.
  • R: 읽기 연산에 대한 정족수. R개 이상 서버로부터 읽기 연산이 성공했다는 응답을 받았으면 해당 연산은 성공한 것으로 간주한다.

정족수 값을 정할 때에는 요구사항에 따라 적절히 값을 정해야 한다. 아래는 몇가지 시나리오에 대한 정족수 선택 케이스다. 원하는 일관성의 수준에 따라 W, R, N 값을 조절하면 된다.

  • R = 1, W = N: 빠른 읽기 연산에 최적화된 시스템
  • W = 1, R = N: 빠른 쓰기 연산에 최적화된 시스템
  • W + R > N: 강한 일관성이 보장되는 시스템
  • W + R ≤ N: 강한 일관성이 보장되지 않는 경우

그렇다면 여기서 나온 ‘강한 일관성’은 무엇일까? 일관성의 수준에 따라 다음과 같이 말할 수 있다.

일관성 모델

  • 강한 일관성 strong consistency: 클라이언트는 절대로 out-of-date된 데이터를 볼 수 없다. 그 어느 시점에 데이터를 조회해도 일관성이 유지된다.
    • 예) 동기화를 동기적으로 실행하는 경우. 즉, 모든 사본에 현재 쓰기 연산의 결과가 반영될 때까지 해당 데이터에 대한 읽기/쓰기 연산을 금지하는 것이다. 고가용성 시스템에는 딱히 적합한 방법은 아니다.
  • 약한 일관성 weak consistency: 읽기 연산을 통해, 가장 최근에 갱신된 결과를 반드시 볼 수 있다는 보장이 없다.
    • 예) 동기화를 비동기적으로 실행하는 경우
  • 최종 일관성 eventual consistency: 약한 일관성의 한 형태다. 갱신 결과가 어느 시점에는 모든 사본에 동기화되지만 그 전까지는 일관성이 깨진 모습을 클라이언트가 조회할 수 있다.

쓰기 연산으로 인한 일관성이 깨지는 문제를 해소하기 위해서는 버저닝 versioning과 벡터 시계 vector clock 기법을 사용할 수 있다. 간단하게 말하자면 데이터 사본의 각 버전을 함께 저장하고, 클라이언트쪽에서 벡터 시계라는 특별한 구조의 데이터를 관리하면서 데이터 충돌 문제를 해소하는 것이다. 클라이언트에서 처리하는 것이기 때문에 클라이언트 구현이 복잡해지고 벡터 시계 용량이 빨리 늘어날 수 있다는 단점이 생기지만, 임계값을 설정하는 등의 방법으로 단점을 극복할 수 있다.

장애 처리

장애 감지

단일 서버만 쓴다면 “서버 A가 죽었습니다. 장애 발생!” 이라고 하면 되지만 서버가 여러개일 때는 좀 다르다. 보통 2대 이상의 서버가 똑같이 서버 A의 장애를 보고해야 해당 서버에 장애가 발생했다고 간주한다. 이를 위한 가장 쉬운 방법은 모든 노드 사이에 멀티캐스팅 채널을 구축하는 것이다. 하지만 서버가 많아질수록 이 방법은 비효율적이게 된다.

가십 프로토콜 gossip protocol 같은 분산형 장애 감지 솔루션을 채택하는게 좋다. 가십 프로토콜은 자신이 살아있음을 박동 카운터 heartbeat counter의 값을 증가시킴으로써 알리고, 다른 노드가 그걸 지켜보면서 누가 죽었는지 판단하는 방법이다. 스스로가 자신의 생존신고를 하고 나머지는 그걸 보다가 일정 시간동안 반응이 없으면 서버 장애가 일어났다고 판단하는 것이다.

장애 처리

장애는 크게 두 종류로 나눌 수 있다. 일시적 장애와 영구적 장애.

일시적 장애로 인해 서버 A가 죽은 경우, 나머지 서버가 해당 서버로 향하는 트래픽을 임시로 처리하면 된다. 장애가 복구되기 전까지의 변경사항을 임시로 기록해두었다가, 장애 복구 이후에 그 기록을 보고 서버 A의 데이터를 보정하는 것이다. 이를 단서 후 임시 위탁 hinted handoff 기법이라고 부른다.

서버 A의 영구적인 장애 상태를 처리하기 위해서 다른 서버의 데이터와 서버 A의 데이터를 서로 비교한 다음 동기화하는 작업이 필요하다. 이를 위해서는 반-엔트로피 프로토콜 anti-entropy protocol을 쓸 수 있다. 각 노드에 보관된 값이나 레이블로부터 계산된 해시값을 사용하여 어떤 부분의 데이터가 다른지 알아내는 기법이다. 이 때 사용하는 해시값을 모아둔 트리를 해시 트리 hash tree, 혹은 머클 트리 Merkle tree 라고 부른다.

머클 트리를 사용하면 좋은 점은 동기화해야 하는 데이터의 양이 두 서버에 저장된 전체 데이터 양에 관계 없이 서로 다른 데이터의 크기에만 비례한다는 점이다. 따라서 두 서버에 저장된 데이터 양이 크다고해서 걱정할 필요가 없다.

요약

분산 시스템 설계를 위해서 신경쓸게 정말 정말 많다. 이런걸 고려해야 한다.

목표/문제사용 가능한 기술
대규모 데이터 저장안정 해시
읽기 연산에 대한 높은 가용성데이터 다중화
쓰기 연산에 대한 높은 가용성버저닝 && 백터 시계
데이터 파티션안정 해시
점진적 규모 확장성안정 해시
다양성안정 해시
조절 가능한 데이터 일관성정족수 합의
일시적 장애 처리느슨한 정족수 프로토콜
영구적 장애 처리머클 트리
데이터 센터 장애 대응여러 데이터센터에 데이터 다중화

여담으로, 이번 장 이름은 "분산 키-값 저장소 설계"였지만 사실 저장소 유형에 관계없이 분산 시스템이라면 모두 통용되는 이야기인 것 같단 생각도 든다. 좀 더 배우다보면 알게 될 것 같다. 어쩜 이렇게 배워야 할게 많은지 😇

profile
설계를 좋아합니다. 코드도 적고 그림도 그리고 글도 씁니다. 넓고 얕은 경험을 쌓고 있습니다.

0개의 댓글