프로그래밍

분산환경에서 Quorum(정족수)은 왜 필요할까 / Quorum이란 무엇인가

2kindsofcs 2021. 11. 5. 00:40

https://aws.amazon.com/ko/blogs/korea/amazon-aurora-under-the-hood-quorum-and-correlated-failure/

 

Amazon Aurora 내부 들여다보기 (1) – 쿼럼 및 상관 오류 해결 방법 | Amazon Web Services

이 글은 AWS Database Blog의 Aurora 집중 해부 시리즈의 Amazon Aurora under the hood: quorums and correlated failure의 한국어 번역으로 AWS코리아의 김상필 솔루션즈 아키텍트가 번역해 주셨습니다. Amazon Aurora 스토

aws.amazon.com

 

쿼럼에 대한 글들은 많지만 다들 쿼럼을 써야한다고만 하고 왜 써야하는지 구체적으로 납득이 가는 수준으로 설명해주는 친절한 글을 찾기가 힘든데, AWS 공식 블로그에 좋은 글이 있었다. 다만 그림으로 예시 없이 읽으니까 조금 아쉬워서 그림을 곁들여서 정리해본다. 

 

 

쿼럼은 AWS Aurora에서만 사용되는 건 (당연히) 아니다. 카프카, 바퀴디비 등 다양한 서비스에서 사용되고 있는 개념이다. 이 서비스들의 공통점은 분산 환경을 전제로 한다는 것이다. 

쿼럼은 무엇이고 왜 분산환경을 대상으로 하는 서비스에서 많이 채택되는가?

쿼럼은 말 그대로 의사 결정에 필요한 정족수다. 표준국어대사전을 찾아보면 정족수는 "합의체가 의사를 진행하고 결정하는 데에 필요한 최소한의 출석 인원"이라고 나와있다. 마치 서킷 브레이커처럼 현실의 어떤 용어가 프로그래밍 쪽에서 꽤 잘 어울리는 형태로(?) 정착한 것 같다. 여튼 정족수라 함은 예를 들어 이런 것이다. 나는 이번달 회식 메뉴를 한우 오마카세로 정하고 싶다. 우리 팀은 5명인데 팀원 중 n명이 동의하면 오마카세를 먹으러 갈 수 있다. 이때 n은 팀원이 총 5명이므로 1 ≤ n ≤ 5이다. 

즉 쿼럼은 좁은 의미에서는 어떤 동작을 하기 위해서 필요한 최소한의, 동등한 무언가들의 찬성표 개수를 뜻한다. 넓은 의미에서는 특정 행위를 하기 위해서 정족수가 필요하다는 규칙을 가리킨다.  

 

 

쿼럼이 무엇인지 확인했으니까 왜 분산환경에서 많이 적용되는지 알아볼 차례이다! 

스플릿 브레인(split brain)이란 클러스터에서 둘 이상의 노드들이 i/o 요청을 처리하는 데 있어서 충돌이 발생하는 상황을 말한다. 노드 그룹 간에 네트워크 연결 단절 등으로 인해 발생할 수 있으며, 당연하게도 공유하고 있던 데이터가 오염되며 데이터 충돌이 발생할 수 있다. (노드들이 모두 죽어버릴 때 발생하는 amnesia 현상도 있는데 이 글에서는 다루지 않는다.) 이를 해결하기 위한 방법 중 하나가 쿼럼이다. 

예를 들어 하나의 primary 노드에 4대의 secondary 노드가 붙어있다고 가정해보자. 그런데 네트워크 문제로 1번, 2번 secondary는 primary와 잘 통신이 되는데 3번, 4번 secondary가 고립되었다. 3번, 4번 secondary는 primary가 죽었다고 생각하고, 적당한 의사소통을 통해 둘 중 하나를 primary로 승격시켜버릴 수 있다. 정작 primary 노드는 멀쩡히 잘 살아있으므로, 데이터 오염이 발생하게 된다. 

이때 "데이터를 쓰기 위해서는 최소 3대의 노드로부터 동의를 얻어야 한다." 라는 쿼럼을 적용한다면 3번, 4번 노드의 경우 정족수를 만족하지 못하므로 데이터를 쓰지 못하게 된다. 데이터가 최신으로 업데이트 되지는 않겠지만 적어도 데이터가 오염되는 상황은 막을 수 있다. 

노드가 하나면 애초에 고민할 필요가 없다. 네트워크가 끊기면 그걸로 그냥 끝이다(점검 걸어야지 뭐...). 하지만 여러 대의 노드를 운영하게 되는 분산환경에서는 스플릿 브레인 문제에 부딪치게 되고, 이를 해결하려고 하다보니 분산환경을 전제로 하는 많은 서비스들이 쿼럼 모델을 사용하는 것이다. 

 

 

이제 쿼럼이 충족해야 할 두 가지 규칙에 대해 알아보자. 

A quorum model
Aurora instead uses a quorum model, where you read from and write to a subset of copies of data. Formally, a quorum system that employs V copies must obey two rules.

First, the read set, Vr, and the write set, Vw, must overlap on at least one copy. This approach means that if you have three copies of data, the read set and the write set can be two, ensuring each sees the other. This rule ensures that a data item is not read and written by two transactions concurrently. It also ensures that the read quorum contains at least one site with the newest version of the data item.

 

AWS 블로그 글에서는 쿼럼 모델은 2가지 규칙을 지켜야 한다고 적혀있다. 

첫 번째 규칙은 read를 하는 카피들과 write를 하는 카피들 중에 반드시 최소 하나는 겹쳐야 한다는 것이다. 그래야 하나의 동일한 item이 2개의 트랜잭션에 의해 동시에 read되고 write되지 않음을 보장할 수 있다. (copy라는 단어가 거슬리면 node라고 생각하자)    

 

간단하게 그림을 그려봤다. 가장 위쪽을 보면 Vw = 2, Vr = 1이며 겹치는 노드의 존재가 보장되지 않는 상황에서의 한 케이스를 나타낸 것이다. 동일한 item에 대해서 copy1과 copy2에서 write가 일어나고 copy3은 read를 하는 문제 상황이 발생할 수 있다. copy1, copy2가 write를 할 때 copy1이나 copy2가 read 요청을 받으면 그런 상황을 예방할 수 있지 않냐고 물을 수 있는데, 맞다. 그런 케이스에는 문제 상황이 발생하지 않겠지만 문제는 특정 copy를 딱 찝어서 read, write 요청을 보내지 않기 때문에 위와 같은 경우의 수가 발생하지 않음을 보장할 수 없다. 마찬가지로 Vw=1, Vr=1인 경우와 Vw=1,Vr=2인 경우에도 동일한 데이터가 동시에 read되고 write되는 상황이 발생할 수 있다. 

 

위 그림은 아까처럼 카피가 3개인데 Vw, Vr에서 겹치는 카피의 존재를 보장하는 경우이다. 어떤 item에 대해서 동시에 write 동작과 read 동작을 하려고 할 때, 3개 카피 중 하나는 반드시 그 2개의 요청을 핸들링하게 되므로 문제 상황을 방지할 수 있다. 위 그림에서 copy3의 경우 read 행위에 대해서만 표를 던지게 되므로 "ok 읽어도 됨" 할 수 있지만 copy2의 경우 "잠깐, 이거 쓰고 있는데? 안돼" 하게 되는 것이다.  

 

 

Second, you need to ensure that the quorum used for a write overlaps with prior write quorums, which is easily done by ensuring that Vw > V/2. This rule ensures that two write operations from two transactions cannot occur concurrently on the same data item. Here are some possible quorum models.

 

두번째 규칙은 write 동작을 할 때 찬성표를 던진 카피들이 반드시 이전 write 동작을 할 때 찬성했던 카피들에 대해 겹치는 카피가 있어야 한다는 것이다. 이러한 규칙이 있으면 동일한 item에 대해서 동시에 두 개의 write 동작이 일어나는 문제 상황을 방지할 수 있다. 이 규칙은 Vw를 전체 노드의 과반수를 초과하도록 설정하면 쉽게 만족된다. 

 

예를 들어 위 그림처럼 copy가 3개라고 가정하자. 3/2는 1.5이므로 Vw는 2이상이어야 한다. 위 경우 Vw는 2이다. (Vw가 3이면 어떤 요청을 처리할 때 존재하는 모든 노드의 허락을 받아야 하는 꼴이므로 이득이 없다)  #1의 경우 write 요청(푸른색)이 들어왔고 copy1과 copy2가 찬성표를 던졌다. 그리고 이어서 또 동일한 item에 대해 write 요청이 들어왔다. copy3이 찬성표를 던져도 copy2가 직전 write를 마치지 않았다면 찬성해주지 않으므로 문제 상황이 예방된다. #2에서처럼 copy1이 copy2보다 먼저 응답해도 마찬가지로 반대를 하게 되므로 역시 문제 상황이 발생하지 않는다. Vw가 과반수를 초과하면 모든 경우에서 Vw에서 최소한 하나는 이전 write 동작을 수행한 copy임이 보장된다. 


 

스플릿 브레인 참고 링크)

https://www.45drives.com/community/articles/what-is-split-brain/

반응형