본문 바로가기
MySQL HA & DR

MySQL Group Replication: Distributed Recovery behind the scenes (번역)

by 모모레 2015. 3. 23.

원본 http://mysqlhighavailability.com/distributed-recovery-behind-the-scenes/



The new addition to the MySQL planet, MySQL Group Replication is now on Labs Release for you to try it! It offers you update everywhere capabilities on any group of normal, out of the box, MySQL servers. Concurrent updates on a setup of several MySQL servers is now possible and this with our trademark: the ease of use.

MySQL Planet에서 새롭게 추가된 MySQL Group Replication은 현재 랩 버전으로 제공되고 있다. 동시에 여러 서버에서 dml을 실행하는게 가능하고, 사용하기에 쉽게 구현되어있다.


In fact we ship MySQL Group Replication in such a way that for you to form a group and add new nodes, all that is needed is to configure the servers with your unique group id and just press start. In this post we show you the “behind the scenes” of this process, on how the node catches up with the remaining servers through distributed recovery.

사실 MySQL Group Replication에서 그룹안에 새로운 노드를 추가하는 것은 서버의 그룹아이디만 추가하여 설정하고, 시작만 하면 된다. 여기에서는 이렇게 동작할때 내부에서 어떤 방식으로 동작하게 되는지 분산 복구 방법에 대해 알아보도록 하자.

The basics about Distributed Recovery

If we were to summarize what distributed recovery is, we could describe it as the process through which a new server gets missing data from a live node, while paying attention to what happens in the group, eventually catching up to the other nodes.

분산 복구가 무엇인지 알기 원한다면, 현재 사용하고 있는 노드로 부터 데이터를 어떻게 새 서버로 전달하는지를 알아야 한다. 그리고 그 작업 동안에 그룹안에서 무슨 일이 발생하는지 주의깊게 봐야 한다. 


This basically defines it, but there is more to it than the simple data transfer.

이것은 기본적으로 정의하지만, 단순한 데이터 전송보다 더 많은 일들이 있다.


In a first phase, the Joiner (joining node), will select one of the online servers on the group for the role of Donor. The Donor is the server responsible for transmitting to the Joiner all the data up to the moment it joined the group and for this to happen, a standard master slave connection will be established between them.

첫번째 단에게서 추가되는 서버(Joiner)는 Donor의 역할을 가진 그룹내의 온라인 서버들 중 하나를 선택해야 한다. Donor는 그룹안에서 투입되는 서버에 대해 데이터를 전송하는 택임을 가진 서버이다. 그러면, 둘 사이에 일반 리플리케이션과 같은 세션이 연결되어 작업이 진행된다.


While the state transfer from the Donor is happening, the plugin is also caching every message that comes from the group. When the first phase ends and the connection to the Donor is closed, the Joiner then starts phase two: the catch up. Here, the Joiner proceeds to the execution of the cached transactions and when the number of transactions queued for execution finally reaches zero, then the node is declared online.

Donor로 부터 데이터 전송이 시작되어 진행되는 동안에, 플러그인은 그룹으로 부터 받은 모든 메세지를 받아서 저장한다. 첫번째 작업이 끝나게 될때 연결은 끊기게 되고, 투입되는 서버를 2번째 단계로 들어가게 된다. 바로 catch up 단계이다. 투입되는 서버(Joiner)는 cach된 트랜잭션을 실행하는 단계에 들어가는 것이다. 그리고, 캐쉬된 트랜잭션의 수가 0이 될 때, 해당 노드는 온라인 상태가 된다.


During this process it is possible for server failures to happen, so recovery also comes with failure handling. Every time a Donor dies, recovery reacts if it is still in phase one, killing the connection and establishing another to a new Donor.

이 프로세스가 진행되는 동안에 서버에 장애가 발생하게 될수도 있다. 그렇게 되면, 장애 검출이 되어 recovery 작업이 진행되는데, 이때 해당 Donor는 죽고, 다른 Donor와 연결하여 다시 1단계에 맞춰 recovery가 진행된다.

 

The entrails of Distributed Recovery(분산 복구 내부 구현방법)

How does the Joiner knows what data it should receive from the Donor?
The answer you are probably thinking is that the mechanism is based on GTID executed sets, but in truth, that is not correct. In fact, distributed recovery works through the use of binlog view change markers.

Joiner가 어떻게 Donor로 부터 받는 데이터가 무엇인지 알까?

이에 대한 대답으로 GTID 구현 방법을 생각해 보면 되지 않을까 한다. 이것이 진실이지만, 정확한것은 아닐수도 있다. 사실 분산 복구는 binlog view change markers를 통해서 이루어진다.

View changes and view ids

To explain the concept of view change markers, lets first define in simple terms what a view and a view change are.

view chanage marker의 개념을 설명하기 위해, 첫번째로 view와 view change에 대해 간단히 정의해야 한다.


A view corresponds to a group of nodes recognized as alive and responding at a moment in time. Thence, any modification to the group like a node joining or leaving is what we name a view change. Any group membership change results in an independent view change communicated to all nodes at the same logic moment. All view changes are also associated to a unique, increasing identifier that we call view change id.

view는 특정 순간에 그룹에 살아있는 노드들을 알려주는 것으로 그 노드들을 말한다. 만약에 그룹의 노드에 어떤 변경이 일어나게 되면 그 변경되는 작업을 view change라고 말한다. 그룹안의 그룹멤버들은 논리적인 순간에 모든 노드들과 통신하여 독립적으로 view 변경을 진행할 수 있다. 그래서 모든 view change는 각자 유일한 id를 가지고 있고, 이 값은 변경이 발생할 때 마다 계속 채번되는 값이 된다.


At the group layer, view changes with their associated view ids are then frontiers between the data exchanged before and after a node joins. What we do here is to transfer this concept into the database layer through a new binlog event: the view change log event. The view id thus becomes a marker as well for transactions transmitted before and after the group change.

그룹레이어에서 관련된 view id를 가진 view change는 노드 추가 후와 데이터 변경 전의 경계가 된다. 우리가 여기서 하는 일은 새로운 바이너리 로그 이벤트를 통해서 데이터베이스 레이어에 개념을 전송하는 것이다. 그 view id는 그룹이 변경되는 전과 후의 트랜잭션을 구분하는 기준점이 된다.

Recovery detailed process

Lets now look at the process, on which the view change id is incorporated into a log event and written to the binlog, step by step:

다음의 프로세스를 보자. view change id는 로그 이벤트안에 기록되어서 바이너리 로그에 기록된다.

  • The stable group(안정된 그룹)

All servers are online and processing transactions from the network. Some servers can be a little delayed in terms transaction execution, but the group acts as one distributed and replicated database.

모든 서버는 온라인 상태이고 네트워크를 통해서 트랜잭션이 ㅣㄹ행된다. 몇몇 서버들은 트랜잭션을 실행하는데 지연이 발생할 수도 있다. 하지만, 그룹의 모든 활동은 분산되어서 전달되었다.

Picture1
Stable server group
  • A node joins(노드 추가)

Whenever a new node joins and the view change is executed, every online server will queue a view change log event for execution. Why do we say queued? Previous to the view change, several transactions can be queued on the node for execution, belonging these to the old view. Queuing the view change event after them guarantees a correct marking of when this happened.

새로운 노드가 추가되면 view change가 실행된다. 모든 오라인 서버는 view change 로그 이벤트르 큐에 저장할 것이다. 왜 정보를 큐에 저장하는 가? view change에 대해 설명했듯이, 몇몇 트랜잭션들은 이전 view id의 값으 가진 상태로 노드에서 실행되기 위해 큐에 저장될 수 있다. 큐에 view change id를 저장하는 이유는 이와 같은 경우에 정확히 트랜잭션을 실행할때 보장해 주기 위해서 이다.


Meanwhile, on the Joiner, there is a Donor selection from the pool of online servers.

한편, Joiner에서는 온라인 상태의 서버 풀 중에 Donor를 선택하게 된다.

A node joins on view 4 and the online nodes write a View change event to the binlog
A node joins
  • State transfer begins ( 주 전송 시작)

When the Joiner selects a Donor, a new master slave connection is established between the two and the state transfer begins. What differentiates this connection is that the Joiner SQL thread is instructed to stop at a new condition: until view id = N.

Joiner가 Donor를 선택할 때 새로운 마스터 슬레이브 연결이 두 서버사이에 생성되어 작업이 시작된다. 이 연결이 다른 일반적인 리플리케이션연결과 다른 점은 joiner sql thread가 view id가 N 이 되는 작업에 도달 할때 해당 세션에 대한 작업을 중지한다는 것이다.


As view ids are transmitted to all nodes in the group at the same logical time, the joiner knows at what view id it should stop. Avoiding tricky GTID set calculations, the view id allows us to clearly mark what data belongs to each group view.

모든 노드에 view id가 전달된 것을 아는 그 순간에 joiner는 그 view id가 중지해야 하는 시점임을 알게 된다. 까다롭게 GTID 값을 계산하지 않고 이와 같은 view id를 통해서 각 그룹의 데이터가 어디까지 속한 것임을 확인할 수 있다.


In the mean, while the Joiner is caching incoming transactions.

이런 이유로 Joiner는 들어오는 트랜잭션을 캐쉬하고 있는 것이다.

A master slave connection is established to the Donor and the data is transfered.
State transfer is executed
  •  State transfer ends

When the Joiner sees an incoming view change log event with the expected view id, the connection is terminated and the server starts applying the cached group transactions. The view change event also plays another role, as conveyor of the certification information associated to the last view. Without it, the Joiner wouldn’t have the information necessary to know how to certify these transactions.

Joiner는 로그 이벤트 정보안에 기대하고 있는 view change log eveint를 확인하면, 세션은 종료되고 서버는 캐쉬한 트랜잭션을 실행한다. view change event는 도다른 역할을 수행하게 되는데, 바로 가장 최신의 view에 대한 인증 정보의 conveyor로서 사용된다. 이 정보가 없으면, Joiner는 해당 트랜잭션이 실행해도 되는 것인지 확인할 길이 없다.


The applying phase duration is not deterministic since it depends on group load. In fact this process does not happen in isolation, as new messages can come in at any time. The number of transactions the node is behind can for this reason vary in time, increasing and decreasing according to the transactional load.

적용 단계에서 걸리는 시간은 그룹안의 부하와 관계되기 때문에 얼마나 걸린다 장담할 수 없다. 사실 이 프로세스는 격리된 상태에서 진행되지 않고, 항상 새 메세지를 받을 수 있는 상태에서 진행되기 때문이다. 하나의 노드에서 실행되어야 하는 트랜잭션은 해당 그룹의 부하상태에 따라 증가 될 수도 있고 줄어들 수도 있다.


When the node queued transactions reach zero and its stored data is equal to the other nodes, its public state changes to online.

저장된 트랜잭션들이 모두 실행되어 없고 제로 상태가 되면 모든 데이터는 저장하고, 다른 노드들과 동일한 상태가 된것임을 의미힌다. 이렇게 되면 Joiner는 온라인 상태로 사용할 수 있게 된다.

The node executes chached transactions.
The Joiner catches up the group

 

Use advice and limitations of Distributed Recovery

When trusting distributed recovery, one must still accept its limitations if the data set to transfer is too big. We are still improving recovery and the plugin’s applier to allow speed ups, but for larger loads its still advisable to provision your server before start.

이와 같은 분산 복구 작업은 전송해야 하는 데이터가 너무 큰 경우에 문제가 될 수 있다. 우리는 아직도 복구 작업에 대한 성능 개션을 위해 노력하고 있고, 속도를 높히려고 하고 있다. 하지만 더부 큰 부하가 예상 되는 경우 서버에 시작전에 미리 준비하는 것도 괜찮은 방법이다.


Currently distributed recovery also suffers from the lack of a view id persistence. This means, that when you shutdown all your nodes, the view id will go back to 0. This is a problem when you bring your nodes back as recovery will not stop at the correct markings. We intend to fix this briefly.

 현재, 분산 복구 작업은 view id 지속성의 부족으로 부터 어려움을 겪고 있다. 이 말은, 사용자가 모든 노드를 shutdown 하는 경우에, view id는 다시 0으로 돌아가는데, 만약, 사용자가 노드를 shutdown 하기 전에 view id로 돌아가고 싶은 상황이라면 문제가 될 수 있다는 것을 의미한다. 우리는 이 문제를 해결하기 위해 현재 노력하고 있다.

Conclusion

With this blog, we hope we gave you a better understanding of how recovery works behind the scenes. On our side we will keep on improving it, be it in better donor selection algorithms, failure detection or other aspects but we also want your opinion!