분산시스템이라면 아래 특징들을 기본으로 가져가야함
자원은 공유하면서, 리소스내에서 동시에 여러가지 작업을 수행한다.
동시 실행 자원을 늘려서 처리량을 늘릴 수 있다.
하나의 서버 안에는 여러 개의 프로세스나 스레드가 있을 수 있고, 이들은 동시에 같은 자원에 접근할 수 있다.
하지만 이 경우, 서버 하나의 리소스 한계 때문에 처리량에 한계가 생긴다.
그래서 분산시스템이 필요하다.
분산시스템은 여러 서버가 동일한 자원에 접근하고, 각자 역할을 나눠 동시에 처리할 수 있어야 한다.
이렇게 동시 실행 자원을 늘려서 전체 처리량을 확실히 늘릴 수 있어야 한다.
단순히 노드 수만 늘린다고 분산시스템이 되는 것은 아니다.
예를 들어, 기존보다 4배 많은 자원을 썼는데 처리량이 1.1배밖에 늘지 않았다면, 이는 제대로 된 동시성이 구현되지 않은 것이다.
이런 경우는 분산시스템이라고 보기 어렵다.
분산시스템은 전체를 통제하는 하나의 Global Clock이 없다
각 노드는 서로 독립적으로, 비동기적으로 동작해야 한다.
어떤 한 노드의 상태나 처리 지연 때문에 다른 노드가 멈추거나 Lock이 걸리거나 병목(Bottleneck)이 생겨서는 안 된다.
물론, 다른 노드가 설정한 값을 참고하거나 영향을 받을 수는 있다.
하지만 그런 영향이 시스템 전체의 흐름을 막아서는 안 된다.
즉, 전체 시스템은 느린 노드 하나 때문에 멈추지 않아야 한다.
각 노드가 독립적으로 동작하면서 전체적으로 일관된 처리가 가능해야 한다.
분산시스템은 어떤 하나의 컴포넌트가 실패하더라도,
그 영향이 시스템 전체로 퍼져 장애가 되면 안 된다.
물론 실제로 구현하다 보면 도미노처럼 연쇄적으로 장애가 발생할 수도 있다.
예를 들어, 잘못된 구조를 설계하거나, 시스템 용량을 너무 작게 잡으면
하나가 죽으면서 다른 친구들도 같이 죽는 상황이 생길 수 있다.
그렇다고 해서 그런 상황이 아예 발생하지 말아야 한다는 뜻은 아니다.
중요한 건, 설계 자체가 하나의 실패가 전체 시스템에 영향을 주지 않도록 되어 있어야 한다는 점이다.
이렇게 실패를 격리할 수 있도록 설계된 시스템,
즉, 한 부분이 고장 나도 나머지는 정상적으로 돌아가는 구조가
바로 분산시스템의 핵심이다.
분산시스템 구현하려면 이런 특징들 고려해야되는데 고려 해봤음?
그리고 어느 수준으로 지켜지는지? 제약사항이나 특별한 사항은 없음?
서로 다른 시스템에 설치를 할 수 있어야 한다. 또한 서로 다른 시스템 사이에 정보와 자원을 공유하며 동작해야한다.
운영체제, HW 에 대한 임팩트가 크기 때문에, OS, HW 관계없이 일관된 개발을 하기 위한 언어를 선택한다.
분산시스템은 서로 다른 구성 요소들 간의 연결과 상호 운용이 가능해야 한다.
즉, 어떤 노드든 일관된 방식으로 다른 노드와 통신하고 동작할 수 있어야 한다.
이를 위해 시스템은 주요 인터페이스를 명확히 노출하고,
통신 방식이 일관되게 유지되어야 한다.
예를 들어, 분산시스템을 구성했다고 하자.
코디네이터 노드 2개, 데이터 노드 3개(d1: 리눅스, d2: Mac, d3: 윈도우)로 만들었다고 가정해보자.
d1(리눅스)은 코디네이터와만 통신하고, 다른 데이터 노드와는 통신하지 않는다.
d2(Mac)는 코디네이터와도, 다른 데이터 노드들과도 모두 통신한다.
d3(윈도우)는 코디네이터와는 통신하지 않고, 데이터 노드랑만 통신한다.
이렇게 되면 통신 방식이 제각각이라서
어떤 노드는 특정 노드와만 연결되고, 어떤 노드는 아예 통신을 못 하기도 한다.
이런 구조는 Openess가 보장되지 않은 상태다.
또한, 운영체제나 구성에 따라 통신 방식이 달라진다면,
Heterogeneity(이질성에 대한 유연성)도 충족하지 못하는 것이다.
즉, Openess란 시스템 내 모든 구성 요소가 일관된 방식으로 연결되고 통신할 수 있도록 열려 있는 것을 의미한다.
서로 프로토콜 기반, 서로 상호 통신이랑 동작이 기능이 달라지지 않고 동일해야된다.
권한 제어 , 접근제어 등이 가능해야 한다. 보통 Security용 프로토콜을 사용하거나 자기들만의 규칙을 정의해서 구현한다.
시스템 자원이나 사용자 수에 따라서 확장 가능해야 한다. 주로 수평적 확장 방법을 사용한다.
Scalability 를 달성하기 위해서는 어떻게 해야될까
cost
of physical resourcesperformance
lossPreventing software resources running out
Running out IP addresses (32 bits in 1970s vs. 128 bits being adopted
requiring modifications to many software components)
Avoiding performance bottlenecks
Name table in DNS was centralized in the past
Now partitioned between servers located throughout the Internet and
administered locally
장애/실패에 대한 대응을 (자동화된 방식으로) 할 수 있어야 한다.
여러 클라이언트가 하나의 공유 자원에 접근하는 등의 동시성에 대한 문제를 해결해야한다.
보통 여러 처리에 대해서 병렬 처리로 진행할 수 있도록 한다.
분산환경에 있는 shared reousrce를 표현하는 대상은 자신의 상태에 대해서 확실히 표현해야한다.
동시성 환경에 안전하려면 하나의 리소스는 consistent 한 상태로 동기화 되어야 한다.
consistent한 상태로만 공유되고 접근될 수 있도록 만드는 것이
동시성 환경에서의 안정성을 보장하는 핵심이다.
이것이 가장 중요한 내용이라고 할 수 있다.
사용자로부터 내부에 있는 정보를 보이지 않게 하고 다음과 같은 투명성을 달성해야한다.
Access transparency
enables local and remote resources to be accessed using identical operations
파일 열기
명령으로 원격 파일도 사용할 수 있게 함Location transparency
enables resources to be accessed without knowledge of their physical or network location (for example, which building or IP address)
Concurrency transparency
enables several processes to operate concurrently using shared resources without interference between them
Replication transparency
enables multiple instances of resources to be used to increase reliability and performance without knowledge of the replicas by users or application programmers
Failure transparency
enables the concealment of faults, allowing users and application programs to complete their tasks despite the failure of hardware or software components
Failure transparency는 하드웨어나 소프트웨어에 장애가 생겨도, 사용자나 애플리케이션이 그걸 직접 느끼지 않고 작업을 계속할 수 있게 해주는 특성이다.
예를 들어, 내가 어떤 분산시스템에서 get 요청을 했는데 실패했다.
이 실패가 단순히 일시적인 네트워크 지연이나 복제 지연 때문에 생긴 거라면, retry하면 성공할 수 있는 실패다. 이럴 땐 프로그램에서 retry 전략을 쓰도록 설계하면 된다.
그런데 만약 같은 실패인데, 실제로는 클러스터 구성이나 하드웨어 설정에 문제가 있어서 운영자가 설정을 바꿔야만 다시 동작하는 상황이라면, 그건 실패가 사용자에게 너무 드러난 거다.
이런 식이면 Failure transparency를 만족하지 못하는 것이다.
또 한 가지 중요한 건, retry가 가능하다는 전제 하에 프로그램들이 짜이게 된다는 점이다. 그래서 분산시스템에서는 idempotent(재시도해도 결과가 같은)한 API 설계를 많이 한다.
그런데 예를 들어, 내가 데이터를 A, B, C 위치에 저장해달라고 요청했는데 retry 했더니 D, E, F 위치에 저장됐다면?
이건 retry 전략이 무너진 거고, 신뢰할 수 없는 시스템이 되는 거다.
즉, 분산시스템은 내부적으로 복잡하고 다양한 장애 상황이 있을 수밖에 없지만, 어떤 종류의 실패가 일어났을 때 사용자가 일관된 방식으로 대응할 수 있어야 한다.
그렇지 않으면 사용자(또는 개발자)는 프로그램을 안정적으로 설계할 수 없다.
Mobility transparency
allows the movement of resources and clients within a system without affecting the operation of users or programs
리소스나 클라이언트가 시스템 내에서 이동해도, 사용자나 프로그램의 동작에는 영향이 없어야 한다는 개념이다. (노트북을 들고 다른 장소로 옮겼더라도 네트워크 연결이나 서비스 사용이 끊기지 않아야 한다.)
분산시스템 내부적으로는 예를 들어 다음과 같이 구성돼 있을 수 있다:
이렇게 리플리카가 구성돼 있기 때문에, node1에 장애가 발생하면 시스템은 자동으로 node2의 데이터를 사용하게 되고, 필요하다면 새로운 노드를 띄워 리플리카를 다시 구성한다.
이처럼 데이터나 리소스가 실제로 이동하더라도, 클라이언트가 접근하는 API나 DNS 주소는 변하지 않아야 한다.
물론 일부 분산 시스템은 클라이언트 라이브러리가 클러스터의 메타데이터를 읽고, "이 키는 node1에 있어" 같은 정보를 기반으로 라우팅을 하기도 한다.
하지만 이런 경우라도 사용자 입장에서는 항상 같은 방식으로 get()을 호출하면, 라이브러리 내부에서 노드 변경이나 재시도 등을 자동으로 처리한다.
결국 시스템 내부에서는 mobility transparency가 완벽하게 구현되지 않을 수 있지만, 클라이언트 API 수준에서는 완벽한 mobility transparency를 제공할 수 있다.
사용자는 데이터가 어디로 옮겨졌는지 몰라도, 항상 같은 인터페이스로 일관된 경험을 제공받는 것, 이것이 mobility transparency의 핵심이다.
Performance transparency
allows the system to be reconfigured to improve
performance as loads vary
Scaling transparency
allows the system and applications to expand in scale without change to the system structure or the application algorithms
Relational Database의 ACID 와 대비되는 개념이다. RDBMS와 같은 Transaction 처리가 필요하다면 ACID가 보장되어야 한다.
BASE의 특징은 모두 immediate consistency 를 포기했기 때문에 가질 수 있는 특성이다.
BASE 원칙은 대규모 분산 시스템에서 "항상 가용성"을 확보하려는 전략으로. 트랜잭션이 반드시 필요한 금융 시스템과는 달리, 소셜 미디어, 광고, 검색, 추천 시스템 등은 BASE 기반의 eventual consistency를 많이 사용한다.
Facebook의 targeting 광고 집행 내역에 대한 리포트를 확인한다. 10분전 데이터까지는 서울 지역에 노출 1만건, 1000건 타게팅 되었다. 그 중 남자는 100명이었다. 10분 후 확인해보니 서울 지역에 노출 1만건, 1060건, 남자는 102명 이었다.
노출건 : 타게팅 : 남자 = 100 : 10 : 1 로 성과를 측정했다. 이것을 기반으로 이후 타게팅 전략을 수정한다.
전 세계에 분산된 네임 서버 구조로 각 DNS 서버의 캐시는 즉각적인 consistency를 보장하지 않음
TTL(time to live) 이후에야 갱신되므로 eventual consistency 기반
C, A, P 로 대표되는 특징 중 분산시스템에서는 3가지를 모두 지원할 수 없고
한 가지는 포기해야
실제 HW/소프트웨어로 구현이 가능
하다는 딜레마.
Consistency(일관성)
Availability(가용성)
Partition-Tolerance(분할내성)
하나의 분산 시스템으로 C,A,P 모두를 완벽히 지원할 수 없다.
Trade-off를 고려해 CA, AP를 가장 많이 선택한다. IT 시스템에서 Availability 는 빠질 수 없는 가장 중요한 요소로 판단하기 때문에 그렇다.
어떤 상황에서도 시스템은 안정적으로 운영되고 Consistency또한 보장된다. 일부만 사용 가능한 상태(부분 가용성)는 허용되지 않는다.
데이터 정합성이 중요한 경우 이러한 특성을 갖는 시스템을 선택한다.
예
그러나 이와 같은 특성은 네트워크 파티션이 발생하는 상황에서는 충족될 수 없다.
왜냐하면, 분산 시스템은 네트워크 파티션이 발생할 가능성을 전제로 설계되기 때문에,
Consistency와 Availability를 동시에 완전히 만족하는(CA) 시스템은 분산 환경에서는 구현할 수 없다.
어떤 상황에서도 시스템은 안정적으로 운영되며, 데이터의 상태와 관계없이 항상 응답을 받을 수 있다.
단, 데이터의 정합성(Consistency)은 보장되지 않는다. 특정 시점에 따라 쓰기(Write)가 동기화되지 않았을 경우, 조회되는 데이터가 달라질 수 있다.
Eventual Consistency: 시간이 지나면 결과적으로는 consistency가 보장된다. (즉각적인 일관성은 제공되지 않는다.)
예
어떤 상황에서도 파티션에 대해서 이용가능하고, Consistency도 보장된다. 파티션 상황에서 Consistency가 가능할 수 없기 때문에, 이런 시스템은 존재할 수 없다.
현실적으로 완벽한 CP, 완벽한 AP 시스템은 존재할 수 없다. 만약 그런 시스템이 있다면,
따라서 AP 와 CP 사이에서 요구사항에 맞는 균형점을 찾아야 한다. (분산시스템에서 파티션은 일어난다고 가정하고)
image source : http://happinessoncode.com/2017/07/29/cap-theorem-and-pacelc-theorem/
CAP 이론의 이러한 단점들을 보완하기 위해 나온 이론이 바로 PACELC 이론이다.
CAP 이론이 네트워크 파티션 상황에서 consistency-availability 축을 이용하여 시스템의 특성을 설명한다면, PACELC 이론은 거기에 정상 상황이라는 새로운 축을 더한다. PACELC는 P(partition)상황에서 A(availability)과 C(consistency)의 상충 관계와 E(else, 정상)상황에서 L(latency)과 C(consistency)의 상충 관계를 설명한다.
PACELC는 CAP 이론을 확장한 개념으로, 시스템이 네트워크 분할(Partition)이 발생했을 때뿐 아니라, 정상적인 상태(Else)에서도 Consistency, Availability, Latency 간의 트레이드오프가 발생한다는 점을 명확히 한다.
시스템은 상황에 따라 다음과 같은 결정을 해야 한다:
[Partition 발생 시]
Consistency 유지 (PC)
Availability 유지 (PA)
[Partition이 발생하지 않은 정상 상태 (Else)]
Latency 우선 (EL)
Consistency 우선 (EC)
PACELC는 단순히 장애 상황뿐 아니라, 정상 동작 중에도 지연시간(latency)과 일관성(consistency)의 균형을 고민해야 함.
image source : http://happinessoncode.com/2017/07/29/cap-theorem-and-pacelc-theorem/
결국 내가 원하는 시스템의 요구사항이 무엇인지 먼저 정의하고, 내가 선택할 수 있는 기술적인 요소들에서 어느 정도까지 구현가능한지 파악한 후, trade-off 를 감안해서 시스템을 구현하고 요구사항이나 기능을 조정해야 한다.
예: 쓰기 응답을 빠르게 주기 위해 일부 노드에만 반영한 후 완료 처리 → eventual consistency
예: 네트워크 파티션 상황에서 일부 노드만 사용 가능한 경우,
응답을 주면 A 유지 / 응답을 막으면 C 유지 → CAP 트레이드오프