[MQ] RabbitMQ 미러링(Mirroring)
Programming

[MQ] RabbitMQ 미러링(Mirroring)

728x90

https://ssup2.github.io/theory_analysis/RabbitMQ_Clustering_Mirroring/

이 글을 이해하기 위해서는 RabbitMQ 클러스터링에 대한 이해가 먼저 필요합니다. 혹시 아직 RabbitMQ 클러스터링에 대해 잘 모르신다면 여기를 먼저 보고와주세요!

 

RabbitMQ 클러스터의 한계

RabbitMQ 클러스터는 "Queue를 제외"한 모든 정보를 모든 노드가 공유한다고 했던것을 기억하시나요? 따라서 결국 모든 클러스터에는 하나의 Unique한 Queue만 존재합니다. 따라서 만약 하나의 노드가 Fail 하는 경우, 다른 노드와 connection을 맺어서 클러스터와의 연결을 유지할 수는 있지만 해당 노드에 속해있던 Queue에 저장된 Message는 유실이 됩니다. 따라서 이같은 Message 유실을 최소화하기 위해 나온 기법이 바로 Queue Mirroring 입니다.

 

Queue 미러링(Mirroring) 이란?

이름 그대로 Queue를 거울에 비춘것처럼 클러스터 내에서 다수의 RabbitMQ 노드에 똑같은 Queue를 생성하고 관리한다 뜻입니다. 위 그림을 살펴보면 기존의 RabbitMQ 클러스터랑은 조금 다른 점을 찾아볼 수 있는데요. 보면 Queue A가 모든 노드에 존재합니다. 따라서 queue 미러링을 하게되면 Exchange 가 하나의 queue에 message를 넣는 것이아니라 미러링된 모든 Queue에 같은 메시지를 쌓습니다. 즉 Queue 미러링을 사용하면 하나의 노드가 죽어도 해당 노드에 존재하는 Queue에 대한 정보가 유실되지 않고 계속해서 Message Consuming이 진행될 수 있는 HA를 구성할 수 있습니다.

 

클러스터에 같은 Queue가 여러개인건 알겠는데 Master-Slave는 뭔가요??

아무리 같은 Queue가 여러 노드에 존재해도 결국 Consumer와 연결되는 Queue는 Master Queue(원본 Queue) 입니다. 이처럼 실제로 consuming 되는 Queue는 Master 이고, Fail에 대비하여 Master와 같은 메시지 정보를 계속해서 보관하면서 대기하고 있는 Queue가 Slave Queue가 됩니다. 따라서 Master Queue와 Slave Queue의 관계는 1:N이며 각 Master Queue 마다 Slave Queue를 몇개로 할지 설정할 수 있습니다.

 

Master-Slave 용어에 관하여: 예전에는 원본 Queue 와 복제된 Queue가 각자 Master와 Slave로 불렸지만 단어 내포하고 있는 좋지않은 의미때문에 현재는 Leader Replica와 Mirror로 불리고 있습니다. 공식문서에서도 이와같은 단어가 사용되는 것을 볼 수 있습니다. 하지만 아직 레거시가 존재하여 HTTP API의 특정 필드 또는 cli 명령어에서는 master, slave 와 같은 명칭이 아직 들어있는 경우가 있습니다. 이 글에서는 쉽고 직관적인 설명을 위해 Master-Slave를 사용하겠습니다.

 

미러링(Mirroring) 과정

기본적으로 Master에 모든 동작이 먼저 실행되고, Slave에 정보가 전파됩니다. Producer는 Master에 message를 전송하고 해당 message는 Slave에 전파됩니다. 그리고 Master에서 message가 consume됐다는 ack를 받게되면 Slave도 message를 drop하면서 모든 Master와 Slave가 동기화됩니다. 중요한건 위에서도 말했듯 아무리 Slave가 많아도 결국 consume이 되는건 Master이기 때문에 Mirroring은 메시지 처리량을 향상시켜주지 않고 오직 HA를 위한 가용성만 높여줍니다.

 

모든 Master-Slave Queue는 항상 동기화가 되나요?

아닙니다! 예를들어 클러스터 구동중에 새로운 노드가 추가되어서 해당 노드에 새로운 Slave가 생기면, Slave는 비어있는 상태에서 Master에서 전파되는 새로운 정보만 들어오게 됩니다. Master가 이미 100개의 message를 가지고 있었다면 새로운 Slave에 기존에 있던 100개의 message가 옮겨지는 것이 아닙니다. 이렇게 되면 Master와 Slave가 가진 정보는 서로 다르게 되고, 이를 Unsynchronized 상태라고 부릅니다. 하지만 이 상태가 계속 지속되는 것은 아닙니다. Master에서 Queue를 소비하다보면 결국 Unsyncronized 상태였던 Slave와 동일하게되어 Synchronized 상태가 됩니다.

 

Master Queue가 있는 노드가 죽으면 어떻게 되나요?

이 상황이 바로 Mirroring이 필요한 상황입니다. Master가 죽게되면 기본적으로 가장 오랫동안 생성돼있던 Slave가 Master로 승격이 됩니다. 이때 기본적으로 Unsynchronized 상태인 Queue는 승격에서 제외됩니다. (파라미터 설정을 통해 Unsynchronized 한 Queue도 승격시킬 수 있지만, Message 유실은 피할 수가 없습니다.

승격되는 과정에서 생기는 message 유실은 없습니다. 만약 새로운 Master가 선출되기 전에 message가 들어온다면 Slave queue에 저장되었다가 승격이 완료되면 Master에 모두 추가됩니다.

상황에 따라 같은 message가 re-consuming 될 가능성도 존재합니다. 만약 message가 consuming 되던중 갑자기 연결이 끊어지게 되면 message가 client에서 consume은 됐지만 받았다는 것을 확인해주는 ack를 못받은상태가 될 수도 있습니다. 따라서 ack를 못받은 message들은 requeue(다시 큐에 집어넣기)가 이루어져서 client 입장에서는 이미 받은 message를 다시 받게 될 수도 있습니다.

 

그럼 모든 Slave가 Unsynchronized 상태면 어떡하나요??

우 Slave에는 없고 Master에만 존재하던 message는 무조건 유실이 됩니다. 그리고 기본적으로 Unsynchronized 상태인 Queue는 승격에서 제외되기 때문에 이 설정을 바꾸지 않았다면 모든 message가 유실됩니다.

 

 

 

출처:
- https://www.rabbitmq.com/ha.html
- https://www.rabbitmq.com/confirms.html
728x90