일관성과 합의 - 데이터 중심 애플리케이션 설계 9장 (2부 끝!)

Broccolism·2022년 3월 21일
3
post-thumbnail

데이터 중심 애플리케이션 설계, 마틴 클레프만 지음. OREILLY.

발생 가능한 문제

지난 장에서는 비공유 분산 시스템에서 발생할 수 있는 문제를 살펴봤다. 네트워크 패킷은 손실, 지연되거나 순서가 흐트러질 수 있다. 시간은 근사치만 알 수 있고 노드는 중단되거나 죽을 수 있다.
9장에서는 이런 문제를 방지하기 위한 해결책을 내놓는다. 한가지 아쉬운 점은, 1대1 대응처럼 앞장에서 살펴본 문제에 대해 '문제:해결책' 형태로 제시한게 아니란 점이다. 대신 좀 더 일반화되고, 광범위한 이야기를 다룬다. '일관성과 합의'라는 9장 제목에 모든 것이 담겨있다.

DB의 역할

문제를 다루는 방식에는 2가지가 있다. 문제를 예방하거나, 해결하거나. 문제 발생 자체를 막을 수 있다면 예방책을 마련하는게 좋다. 하지만 앞에서 살펴본 문제는 발생 자체를 막기 어려운 문제다.
이런 상황에서 데이터베이스가 할 일은 이미 일어난 문제를 잘 해결하는 것이다. 네트워크 지연이 발생하고 시계가 정확하지 않아도 데이터의 일관성을 보장하는 것, 이게 DB의 역할이다.

일관성과 성능 사이

  • 최종적 일관성: 데이터베이스에 쓰기를 멈추고 불특정 시간 동안 기다리면 결국 모든 읽기 요청이 같은 값을 반환한다. 이를 보장하는 데이터베이스는 최종적 일관성을 보장한다고 표현한다.

모든 데이터베이스가 최종적 일관성을 보장해야 할 것처럼 보인다. 하지만 무조건 일관성만 챙겨선 안된다. DB가 강한 일관성을 보장하고 싶다면 그만큼 대가를 치러야하기 때문이다. 그 대가는 성능과 내결함성이다. 우리는 이미 앞장에서 네트워크 비용과 성능 사이의 trade-off 사례를 봤다. 일관성과 성능/내결함성 사이에도 trade-off가 존재한다.

선형성

9장에는 용어가 많이 등장하고, 또 끝까지 등장한다. (그래서 이번 장이 지금까지 본 장 중에 제일 읽기 어려웠다. 이 글을 쓰는 지금도 100% 이해는 못했다. 🥲) 가장 많이 나온 단어 중 하나가 선형성 (linearizability)이다.

데이터베이스 복제본이 하나만 있다는 환상을 만들어준다면 훨씬 더 단순해지지 않을까?

선형성이 등장한 배경이다. 선형성을 보장하는 DB는 모든 연산을 하나의 전체 순서가 정해진 타임라인에 넣는다. DB 복사본이 N개가 아니라 단 1개만 있다고 생각해보자. 이 때 일어나는 일이 곧 선형성이 보장되었을 때 일어나는 일과 같다. 예를 들어, 팔로워가 여러개인 단일 리더 시스템에서 일어났던 복제 지연 문제는 더이상 일어나지 않을 것이다. 책에는 이보다 더 구체적인 예시가 그림과 함께 친절하게 설명되어 있다.

선형성이 유용해지는 영역 몇가지가 있다.

  • 잠금과 리더 선출: 단일 리더 복제 사용 시, 스플릿 브레인이 일어나지 않게 막아야 한다.
  • 유일성 제약 조건: 파일 저장 서비스에서 경로와 파일 이름이 동일한 파일이 2개 이상 존재할 수 없다.

성능과의 트레이드 오프

선형성은 느리다.

앞서 말했듯이 선형성을 보장하다보면 성능을 포기해야 할 때가 온다. 그래서 선형성 보장을 제공하지 않기로 한 분산 데이터베이스도 있다. 선형성이 느린 원인은 네트워크 지연 때문이 아니라, 선형성 자체의 성질 때문이다.

선형성을 기가 막히게 잘 구현해서 빠르게 작동하도록 하는 알고리즘은 아직까지 나오지 않았다고 한다. 하지만 아주 강력한 선형성을 포기하고 적당히 완화된 모델을 사용하면 성능도 챙길 수 있다. 12장에서는 이와 관련된 얘기가 나온다고 한다.

합의

분산 시스템에서 가장 근본적인 문제다. 인터넷 세계가 전세계인의 의 덕분에 굴러가듯 분산 시스템에서도 합의가 중요하다. 단일 리더 시스템에서는 누가 리더인지 합의를 봐야 하고, 리더가 죽고나서 누가 어떻게 새 리더가 될 것인지도 합의 해야 한다.

모든건 합의 문제로 돌아간다

앞에서 나왔던 잠금과 리더 선출, 유일성 제약 조건을 포함해서 다양한 문제가 결국에는 합의 문제임이 이번 장에서 밝혀진다. 데이터베이스에서 일관성을 지키기 위한 모델에는 2가지가 있는데, 바로 선형성과 인과성이다. 선형성은 total order를, 인과성은 partial order를 보장한다. 그런데 이 둘도 결국에는 합의 문제로 환원된다. 따라서 이 책의 전체 내용도 결국에는 합의를 다루는 것이라는 내용도 나온다.

2PC: 2-Phase Commit

이해하기 쉬운 합의 알고리즘을 가져와봤다. 2단계 커밋이다. 여러 노드에 걸친 원자적 트랜잭션 커밋을 보장한다. 즉, 모든 노드가 커밋되거나 모든 노드가 어보트되도록 보장한다.

2-phase인 이유는 이 알고리즘을 수행하는 주체가 2가지로 나뉘기 때문이다. 바로 코디네이터(혹은, 트랜잭션 관리자)와 참여자다. 코디네이터가 전체 흐름을 관장하고 참여자가 신호를 보내는 역할이다. 참여자의 판단 하에 수정 내용은 커밋되거나 어보트된다. 책에서는 이 방식에 대한 자세한 설명과 함께 장애 발생 가능성을 알려주고, 더 나아가 3단계 커밋이 등장하기도 한다.

합의 알고리즘

합의 알고리즘이 만족해야하는 조건이 몇가지 있다.

  • 균일한 동의: 어떤 두 노드도 다르게 결정하지 않는다.
    • 노드 A가 생각한 리더와 노드 B가 생각한 리더는 같아야한다.
  • 무결성: 어던 노드도 두 번 결정하지 않는다.
  • 유효성: 한 노드가 값 V를 결정한다면 V는 어떤 노드에서 제안된 것이다.
    • 아무도 제안하지 않은 값을 결정하는 노드는 없어야 한다.
  • 종료: 죽지 않은 모든 노드는 결국 어떤 값을 결정한다.

합의 코디네이션 서비스

아파치 주키퍼처럼 분산 시스템에서 노드 간의 합의를 도와주는 서비스가 있다. 책에서는 이런 서비스에 대한 이야기도 간간히 나온다. 일반적으로 개발자가 직접 코디네이션 서비스를 다룰 일은 잘 없고, HBase나 하둡 얀 같은 분산 시스템이 코디네이션 서비스에 의존하는 경우가 많다.


여담

이번 장 포스팅이 짧은 이유는 딱 이만큼만 제대로 이해했기 때문이다. CAP 정리, 순서화 보장과 순서 브로드캐스트 등 다른 내용도 많이 있었지만 책을 뒤져보지 않고 온전히 글로 풀어서 쓸 수 있는건 이정도인 것 같다. 언젠가 이 포스팅에 더 많은 내용을 채워넣을 수 있게 되면 좋겠다. 😇

이번 장을 보면서 자연의 법칙이 아닌 인간이 만들어낸 기술에서는 항상 규칙을 만들고 그 규칙을 따르면서 시스템이 유지되는 것 같다는 생각이 들었다. 그러니까 합의라는 단어로 세상이 돌아가는거다. 당장 생각나는 것만 해도 HTTP, OS 보안 시스템 등이 있고, 기술 이외 우리 삶 속 다양한 분야도 결국 합의로 이루어진 부분이 많다. 우리의 삶이 규칙으로 이루어져있기 때문에 자연 속에서도 자연의 법칙, 규칙 같은걸 찾으려 하는게 아닐까?

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

2개의 댓글

comment-user-thumbnail
2022년 3월 24일

항상 좋은 글 감사합니다 ㅎㅎ

1개의 답글