처음에는 서버가 단 한 대만 있다고 가정해보자.
DNS에는 서버의 IP를 물려놨을 것이다.
그럼 서버가 사망하셨을 때나 트래픽이 몰렸을 때 레이턴시가 커지거나 제대로 된 응답을 받지 못한다.
이를 위해 Load Balancing이란 기술을 사용한다.

Load Balancing

간단하게 서버를 두 대 두고 로드 밸런서(하드웨어/소프트웨어)를 통해 트래픽을 분산시킨다고 가정해보자.
DNS에는 로드 밸런서의 주소를 물려놨을 것이다.
그럼 한 대의 서버가 사망해도 장애가 발생하지 않고, 트래픽을 알고리즘에 따라 분산시키기 때문에 좀 더 레이턴시가 줄어들 것이다.
하지만 로드 밸런서 님께서 사망하시면…?
따라서 로드 밸런서 조차도 이중화시키고 DNS에는 그 이중화한 주소를 등록하게 된다.

하지만 여기서 문제가 발생한다.
HTTP는 Stateless 프로토콜이기 때문에 쿠키와 세션을 통해 State를 유지한다.
(클라가 보낸 쿠키를 통해 서버에 저장된 세션을 가지고 와서 State를 유지…
쿠키는 조작될 가능성이 있기 때문에 세션을 식별하기 위한 수단으로만 사용하고 암호화해서 관리해야함.)
A란 유저의 세션이 host-1이라는 서버에 저장돼있다고 가정해보자.
분산 알고리즘에 따라 A 유저의 요청이 host-2로 갔다고 가정해보자.
그럼 이 유저는 로그인한 상태나 기타 등등의 정보가 유지되지 않는 것이다.
어떤 때는 로그인 됐다고 나오고, 어떤 때는 로그인 안 됐다고 나오면 유저 입장에서는 화날 것이다.
이럴 때 사용하는 게 Sticky Session이다.
Sticky(끈적거리는…) 해당 세션은 끈적거려서 다른 호스트로 가는 걸 못 가게 붙잡는다는 의미 같다.
여튼 유저 A의 요청은 처음에 해당 유저의 세션을 저장한 서버로만 간다는 걸 의미한다.
따라서 좀 헤비한 유저는 해당 서버에 요청이 몰릴 것이므로 헤비한 유저의 세션만 따로 저장하는 서버를 둔다거나 여러가지 전략을 세우기도 한다.

하지만 여기서 또 문제가 발생한다.
유저 A의 세션을 가지고 있는 host-1이라는 서버가 사망한다고 가정해보자.
서비스 전체에 장애는 나지 않지만, 유저 A의 세션이 유실됐으므로 로그인이나 기타 등등의 정보는 날아간다.
유저는 갑자기 로그인이 돼있지 않는다는 황당한 오류 문구를 보게될 것이다.
이를 위해 클러스터링이란 개념이 등장했다.

Clustering

클러스터는 일반적으로 무리나 (포도) 송이 등등을 일컫는다.
데이터 분석이나 머신 러닝 쪽에서는 유사하거나 서로 관련있는 항목끼리 묶어서 기억하려는 경향 같은 걸로 해석한다.
이와 유사하게 컴퓨터 사이언스 쪽에서는 여러 대의 컴퓨터들이 연결되어 하나의 시스템처럼 동작하는 컴퓨터들의 집합 으로 해석한다.

cluster-1에 host-1-a, host-1-b 두 대의 서버가 존재하고,
cluster-2에 host-2-a, host-2-b 두 대의 서버가 존재한다. (각 컴퓨터는 병렬로 연결돼있다.)
총 4대의 서버가 존재하는 것이다.
그리고 로드 밸런서에는 cluster-1과 cluster-2가 물려있고, dns에는 이중화된 로드 밸런서의 주소가 물려있다.
이렇게 되면 host-1-a, host-1-b 두 대의 서버가 모두 사망하시면 어쩔 수 없겠지만…
host-1-a만 사망하셨을 때는 A 유저의 세션이 유실되지 않는다.

외부에서는 그냥 cluster-1만 존재하는 거지, 그 안에 어떻게 구성돼있는지는 중요하지 않다.
클러스터 내부의 서버들 사이에서도 어떻게 복사하고 싱크를 맞출 것인지는… 굉장히 어려운 일일 것이다.

하지만 클러스터링도 만능은 아니다. (뭐 만능이 어디 있겠냐만은…)
위에 얘기한 거처럼 클러스터 내의 모든 호스트가 사망하는 경우에도 문제가 되고,
클러스터를 하나 늘렸을 때는 새로운 클러스터에는 요청이 잘 들어오지 않아 비교적 한산하게 된다.
뭐 서비스를 계속 하다보면 해당 클러스터에도 자연스레 요청이 늘어나긴 하겠지만 그 전까지는 서버를 놀리는 셈이 된다.
이를 위해서 분산 세션 관리가 등장했다.

Distributed Session Manager

우선 분산 세션 관리를 하게 되면 Sticky Session을 사용하지 않아도 된다.
그럼 자연스레 굳이 클러스터링을 하지 않아도 되고,(복잡도 감소)
자연스레 분산 알고리즘의 복잡도도 줄어들게 된다. (헤비한 유저를 한 쪽 서버에 몰거나 기타 등등의 뻘짓을 안 해도 되기 때문에…)

우선 유저의 세션을 웹 서버에서 관리하지 않고 별도의 공간에서 관리하면 된다.
이 별도의 공간은 세션을 저장하기 딱인 캐시(인메모리 DB의 일종인 Redis, Memcached)가 안성 맞춤이다.
또한 분산하는 목적은 단일 노드가 사망해서 장애가 나는 경우를 없애고자 서버를 여러 대로 나눠서 분산해서 저장하는 것이다.
분산해서 저장할 때도 노드 하나(마스터)에 모든 데이터 다 때려박고 나머지 노드에 전부 복제하면 좋겠지만…
성능이 좋은 장비를 써야하고, 복제하는데 분산된 모든 장비에 전파되기까지 시간도 걸릴 것이다.
따라서 비교적 싼 장비를 통해 여러 장비에 샤딩을 하게 된다.
또한 유저 A의 세션을 저장한 장비가 사망해서 유저 A의 세션을 유실시키면 안 되기 때문에 클러스터링을 해야한다.
또 세션 생성보다는 조회하는 게 훨씬 많을 것이므로 리플리케이션(슬레이브, Read Only)도 구성해두면 좋은 성능을 가져갈 수 있다.