공통/인프라 & 시스템 설계

[대규모 시스템 설계 기초 정리] 분산 키-값 저장소 with Cassandra DB

반응형

요구사항

  • 높은 가용성을 제공.
  • 높은 규모 확장성을 제공.
  • 데이터 일관성 수준은 조정이 가능해야 한다.


단일 서버  Key-Value  저장소


모든 데이터를 단일 서버 Key-Value 저장소 내의 메모리에 해시 테이블로 저장하는 경우, 모든 데이터를 메모리에 두는 것이 불가능하며

  • 데이터 압축 혹은 자주 쓰이는 데이터만 메모리에 두고 나머지는 디스크에 저장을 통해 어느정도 개선은 가능해도 한계가 존재한다.


분산  Key-Value 저장소


  • 분산 키 값 저장소는 분산 해시 테이블이라고도 하며,  Key-Value 쌍을 여러 서버에 분산시키는 것이다.


CAP 정리

  • 데이터 일관성 (Consistency), 가용성 (Availability), 파티션 감내 (Partition tolerance)라는 세 가지 요구사항을 동시에 만족하는 분산 시스템을 설계하는 것은 불가능하다는 정리.
  • CAP 중 어떤 두 가지를 충족하려면 나머지 하나는 반드시 희생해야 한다는 것


데이터 일관성

  • 분산 시스템에 접속하는 모든 클라이언트는 어떤 노드에 접속했느냐에 관계없이 언제나 같은 데이터를 보게 되어야 한다.


가용성

  • 분산 시스템에 접속하는 클라이언트는 일부 노드에 장애가 발생하더라도 항상 응답을 받을 수 있어야 한다.


파티션 감내

  • 장애가 발생하더라도 시스템은 계속 동작해야 한다는 것.

일반적으로 네트워크 장애는 피할 수 없는 일로 여겨지므로, 분산 시스템은 반드시 파티션 문제를 감내할 수 있도록 설계되어야 한다. 따라서 CAP 중 P는 항상 감내할 수 있도로 설계해야 한다.

그래서 보통 CA 시스템, AP 시스템이 존재한다.


CA 시스템 vs AP 시스템

분산 시스템은 파티션 문제를 피할 수 없다. 파티션 문제가 발생하면 일관성과 가용성 사이에 하나를 선택해야 한다.

가용성 대신 일관성을 선택하는 경우

  • 여러 서버 사이에 생길 수 있는 데이터 불일치 문제를 피하기 위해 장애가 발생한 서버 이외의 다른 서버에 대해 쓰기 연산을 중단시켜야 하는데, 이럴 경우 가용성이 깨진다.
  • 은행권 시스템은 보통 데이터 일관성을 양보하지 않는다.


일관성 대신 가용성을 선택하는 경우

  • 설사 최신 갱신된 데이터가 아닌 낡은 데이터를 반환할 위험이 있더라도 계속 읽기 연산을 허용해야 한다.
  • 따라서 다른 서버에 계속 쓰기 연산을 허용할 것이고, 장애가 발생한 서버가 파티션 문제가 해결 된 이후에 새 데이터를 복구된 서버에 전송하게 된다.


데이터 파티션


  • 대규모 애플리케이션의 경우 전체 데이터를 한 대 서버에 모두 넣는 것은 불가능하다.
  • 가장 단순한 해결책은 데이터를 작은 파티션들로 분할한 다음 여러 대 서버에 저장하는 것인데, 다음 두 가지 문제를 중요하게 따져봐야 한다.
    • 데이터를 여러 노드에 고르게 분산할 수 있는지
    • 노드가 추가되거나 삭제될 때 데이터의 이동을 최소화할 수 있는지

이런 문제를 푸는 데 적합한 기술은 안정 해시로 지난 장의 내용을 확인하자.


데이터 다중화


  • 높은 가용성과 안정성을 확보하기 위해 데이터를 N개의 서버에 비동기적으로 다중화할 필요가 있다.
  • N개의 서버를 선정하는 방법은 어떤 키를 해시 링 위애 배치한 후, 먼저 만나는 N개 서버에 데이터 사본을 보관하는 방법이 있다.
    • 가상 노드를 사용한다면 N개의 노드가 실제 물리 서버 N개가 아닐 수도 있는데, 이러한 문제를 피하려면 노드를 선택할 때 같은 물리 서버를 중복 선택하지 않도록 해야 한다.
    • 같은 데이터 센터에 속한 노드는 정전, 네트워크 이슈 등 문제를 동시에 겪을 가능성이 있기 때문에 안정성을 담보하기 위해 데이터의 사본은 다른 센터의 서버에 보관하고, 센터들은 고속 네트워크로 연결해야 한다. (Cassandra DB에서 Keyspace를 생성할 때, Networktopologystrategy 전략을 사용하면 여러 데이터 센터에 걸쳐 데이터를 복사하게 된다.)


데이터 일관성


  • 여러 노드에 다중화된 데이터는 적절히 동기화가 되어야 한다.
  • 정족수 합 (Quorum Consensus) 프로토콜을 사용하면 읽기/쓰기 모두에 일관성을 보장할 수 있다.


N = 사본 개수

W = 쓰기 연산에 대한 정족수 (쓰기 연산이 성공한 것으로 간주되려면 적어도 W개의 서버로부터 쓰기 연산이 성공했다는 응답을 받아야 함)

R = 읽기 연산에 대한 정족수 (읽기 연산이 성공한 것으로 간주되려면 적어도 R개의 서버로부터 응답을 받아야 함)


W, R, N의 값을 정하는 것은 응답 지연과 데이터 일관성 사이의 타협점을 찾는 전형적인 과정이다.

  • W=1 또는 R=1인 구성의경우 중재자는 한 대 서버로부터의 응답을 받으면 되니 응답속도는 빠른 반면, 데이터 일관성의 수준은 떨어진다.
  • 반면 W나 R의 값이 1보다 큰 경우는, 데이터 일관성의 수준은 향상되지만, 응답 속도는 느려질 것이다.


R=1, W=N

  • 빠른 읽기 연산에 최적화된 시스템


W=1, R=N

  • 빠른 쓰기 연산에 최적화된 시스템


W + R > N

  • 강한 일관성이 보장됨 (보통 N=3, W=R=2)


W + R ≤ N

  • 강한 일관성이 보장되지 않음


일관성 모델


데이터 일관성의 수준을 결정하는데 여러 종류가 있다.

  • 강한 일관성
    • 모든 읽기 연산은 가장 최근에 갱신된 결과를 반환한다.
    • 모든 사본에 쓰기 연산의 결과가 반영될 때까지 해당 데이터에 대한 읽기/쓰기를 금지하는 것 (고가용성 시스템에 적합하지 않음)
  • 약한 일관성
    • 읽기 연산은 가장 최근에 갱신된 결과를 반환하지 못할 수 있다.
    • AWS Dynamo, Cassandra DB는 최종 일관성 모델을 택하고 있음.
  • 최종 일관성
    • 약한 일관성의 한 형태로, 갱신 결과가 결국에는 모든 사본에 갱신되는 모델

최종 일관성 모델을 따를 경우, 쓰기 연산이 병렬적으로 발생하면 시스템에 저장된 값의 일관성이 깨어질 수 있는데, 이 문제는 클라이언트가 해결해야 한다.


일관성이 깨진 데이터를 읽지 않도록 하는 기법은 다음과 같은 방법이 존재한다.

  • 데이터 버저닝
    • 버저닝은 데이터를 변경할 때마다 해당 데이터의 새로운 버전을 만드는 것.


장애 처리


  • 대규모 시스템에서 장애는 그저 불가피하기만 한 것이 아니라 아주 흔하게 벌어지는 사건이다.
  • 따라서 장애를 어떻게 처리할 것이냐 하는 것은 굉장히 중요한 문제이다.


장애 감지

  • 모든 노드 사이에 멀티 캐스팅 채널을 구축하는 것이 서버 장애를 감지하는 가장 손쉬운 방법이지만, 비효율적이다.
  • Gossip Protocola 같은 분산형 장애 감지 설루션을 채택하는 것이 더 효율적임.


Gossip Protocol 원리

  • 각 노드는 멤버십 목록을 유지한다. (멤버십 목록은 각 멤버 ID와 그 박동 카운터 쌍의 목록)
  • 각 노드는 주기적으로 자신 박동 카룬터를 증가시키고, 무작위로 선정된 노드들에게 주기적으로 자기 박동 카운터 목록을 보낸다.
  • 박동 카운터 목록을 받은 노드는 멤버십 목록을 최신 값으로 갱신한다.
  • 어떤 멤버의 박동 카운터 값이 지정된 시간 동안 갱신되지 않으면 해당 멤버는 장애 상태인 것으로 간주한다.


일시적 장애 처리

Gossip Protocol로 장애를 감지한 시스템은 가용성을 보장하기 위해 필요한 조치를 해야 한다.

  • 엄격한 정족수 접근법을 쓴다면, 읽기와 쓰기 연산을 금지해야 할 것.
  • 느슨한 정족수 접근법은 이 조건을 완화하여 가용성을 높인다.
  • 네트워크나 서버 문제로 장애 상태인 서버로 가는 요청은 다른 서버가 잠시 맡아 처리한다.
    • 그동안 발생한 변경사항은 해당 서버가 복구되었을 때 일괄 반영하여 데이터 일관성을 보존한다.
    • 임시로 쓰기 연산을 처리한 서버에는 그에 관한 단서를 남겨두는데, 이런 장애 처리 방안을 단서 후 임시 위탁 (hinted handoff) 기법이라고 한다.


영구 장애 처리

영구적인 노드의 장애 상태를 처리하기 위해 반-엔트로피 프로토콜을 구현하여 사본들을 동기화할 것이다.


데이터 센터 장애 처리

  • 데이터 센터 장애에 대응할 수 있는 시스템을 만들려면 데이터를 여러 데이터 센터에 다중화하는 것이 중요하다.
  • 한 데이터센터가 완전히 망가져도 다른 데이터센터에 보관된 데이터를 이용할 수 있을 것.


Cassandra 시스템 아키텍처


  • Coordinate는 클라이언트에게 Key-Value 저장소에 대한 프락시 역할을 하는 노드.
  • 노드는 안정 해시의 해시 링 위에 분포한다.
  • 노드를 자동으로 추가 또는 삭제할 수 있도록, 시스템은 완전히 분산된다.
  • 데이터는 여러 노드에 다중화된다.
  • 모든 노드가 같은 책임을 지므로, SPOF는 존재하지 않는다.


쓰기 동작 방식

  • 쓰기 요청이 들어오면 커밋 로그 파일에 기록한다. (디스크에 저장함으로써 이후 서버에 장애가 발생해도 복구가 가능)
  • 데이터가 메모리 캐시에 기록된다 (카산드라의 경우 memtable)
  • 메모리 캐시 혹은 커밋 로그 파일이 가득차는 등의 특정 상황 시 데이터가 디스크에 있는 SSTable에 기록된다. (flush 과정이라고 한다)


읽기 동작 방식

  • 읽기 요청을 받은 노드는 데이터가 메모리 캐시에 있는지 부터 확인한 후, 있으면 해당 데이터를 클라이언트에게 반환한다.
  • 메모리에 없는 경우 디스크에서 가져와야 하는데. 여러 SSTable 중 찾는 키가 어디에 있는지 알아낼 효율적인 방법으로 Bllom filter가 사용된다. (Bloom filter를 통해 어떤 SSTable에 키가 보관되어 있는지 알아낸다.)
  • SSTable에서 데이터를 가져와서 클라이언트에게 반환한다.


참고

 
반응형