(kafka) 장애 복구 정리

1. WAS -> Kafka (연결불가능)

이 경우 Producer(소셜엔진) 에서 카프카로 데이터 전송시 exception이 발생
이 exception을 소셜엔진엔서 callback을 이용해 실패로그로 저장하던지 MongoDB에 저장하여 실패 데이터를 기록
이와 같은 케이스는 다음과 같은 방법으로 실패를 처리할 수 있다


1) retries 옵션에 적당한 값을 설정해 실패 시 재시도 (엄청난 지연 발생가능)
2) 전송 실패시 발생하는 Exception을 catch에 큐에저장 후 다시 재전송
실패가 지속되면 카프카 문제로 판단해 실패로그를 저장 혹은 MongoDB 에 해당 데이터 저장

참고 : http://readme.skplanet.com/?p=13042

Scenario 1 - Fire-and-forget with a failed node and partition leader fail-over (acks=0)


이 케이스는 프로듀서에서 acknowledgements를 받지 않는다. 즉, 전송만 계속하는 것으로
만약 현재 카프카 호스트의 Leader 가 다운된다면
가정) 약 10만개 메시지 전송 중, 3만개 메시지 전송 중, 카프카 leader가 down되었을 때
새로운 leader를 선출하게된다.
이 텀동안 데이터 유실이 발생 약 6700여개 메시지 전송 실패


Scenario 2 - Acks=1 with a failed node and partition leader fail-over

ack0=1인 경우, Leader노드가 fail된 경우. 이 케이스 또한 데이터 유실이 발생한다.
그러나 acks=0 인 경우보다 데이터 유실 발생이 더 적다.

테스트) 10만 메시지를 한개의 Producer에서 전송했을 때, 3만번쨰에서 Leader가 죽고,
새로운 Leader 가 선출되었을때, 약 5개의 데이터 손실 발생, 약 9만개 메시지는 Producer 에 응답함


Scenario 3 - Acks=all with a failed node and partition leader fail-over (No message loss)

10개의 프로듀서가 병렬로 카프카에 10만개 메시지 전송하는 상황
10초후 카프카 Leader가 죽은 상황, 이 케이스는 데이터 손실이 발생하지 않는다.

Scenario 4 - Completely Isolate Leader from other Kafka nodes and Zookeeper with acks=1

카프카 리더가 고립되는 것인 완전히 down되는것보다 더 큰 메시지 손실이 발생한다. (카프카 리더가 고립되면 그동안 리더는 계속해서 메시지를 받고 있는다.) 왜냐하면 주키퍼와 통신하지 않아 주키퍼는 해당 파티션이 끊긴것으로 판단한다. (음..그러면 min.sync.replica=2로하게되면 메시지 손실을 방지할수 있지않을까?)

리더노드가 완전히 고립되는것이 단순히 실패하는것보다(acks=1) 더 상황이 안좋다.
이때 리더가 주키퍼와 연결이 끊긴것을 판단할 때까지 데이터 손실이 발생한다.
왜냐하면 프로듀서측에서는 리더가 존재하는것으로 파악하고 해당 파티션에 메시지를 전송하기 떄문이다.

테스트) 1초당 약 10만개의 메시지를 전송한다고 보자
3만개 메시지를 전송할 때즘 , 카프카 Leader가 주키퍼와도 연락이 끊기고 나머지 브로커의 follower들과도 연락이 끊긴다.
약 6만개 메시지가 전송 되었을 때 쯤, 타임아웃이 발생하고 프로듀서 측으로 응답을 보낸다. 그 후 새로운 Leader가 선출되어 데이터 유실을 확인한 결과
약 31784개의 데이터 유실이 발생했다.

테스트2) 약 100개의 메시지를 느리게 전송하고 있을때, 약 13~14번째 메시지 전송시 Leader가 고립되면 28개의 메시지를 전송할 때 쯤, 프로듀서 측에 Leader가 고립되었다는 응답을 보낸다. 대략 60초 동안 정지가 지속되고, 약 60초 후부터 프로듀서는 새로운 Leader에 메시지를 전송한다.


결과적으로  acks=1일때 단순히 리더노드가 다운되는것보다, 주키퍼와 연락도 끊기고 다른 노드들과도 연결이 끊기는 케이스가 더 많은 데이터 손실이 발생한다.


Scenario 5 - Completely Isolate Leader from other Kafka nodes and Zookeeper with acks=all (no message loss)

이 경우는 Leader 가 다운되는 경우, 어떠한 ack도 발생하지 않는다.
10초가 지난후 Leader는 ISR로부터 제외된다.(아직 주키퍼로부터 업데이트는 발생하지않음) 그후 데이터 입력을 거절한다.
그 후, follower는 새로운 Leader로 승격되고, 프로듀서는 60초안에 리더를 찾아 다시 메시지 전송을 시작한다.



Scenario 6 - Leader Isolated from Zookeeper only with Acks=1

주키퍼와 connect가 끊기고, 다른 노드들과는 connect 가 유지되는 케이스
카프카 브로커의 리더가 주키퍼와 connect 되지 않는 경우, 주키퍼는 해당 노드를 죽은 것을 판정하고
남은 follower노드들 중 하나를 리더로 선정한다. 그동안 오리지널 리더는 프로듀서로 부터 메시지를 계속 받는다. (이미 다른 리더가 결정되었더라도 )
이때, 이미 죽은 리더로부터 acknowledged 받은 메시지들은 손실된다.

이 케이스는 시나리오 4인 카프카 리더가 다른 follower노드들과 주키퍼와 connect가 끊어진 경우와 비슷하다.

비슷한점은 follower들은 리더로부터 request를 보내 데이터를 가져오는 것을 멈추게되고 그렇게 되면서 leader ISR로부터 자진해서 떨어진다.
차이점은 새로운 리더가 선출되었을때, follower들은 fetch request하는 것을 멈춘다.
controller노드 같은 경우도 , 주키퍼와 리더가 연락이 끊겼기 때문에 해당 리더노드가 offline 이라고 판명한다. 그래서 데이터를 복수 할 수 없다.
ack=1인경우라도 주키퍼와 connect가 끊기면 데이터 손실이 발생한다



Scenario 7 - Leader Isolated from Zookeeper only with Acks=all (no message loss)

이 케이스도 데이터 손실이 발생하지 않는다. 이 경우 controller은 리더에게 "리더를 멈추라"라고 명령할 수 없다. 여전히 controller입장에서는 해당 노드를 리더로 생각한다. 다른 follower들은 fetch request보내는 것을 멈춘다. 그후 Leader는 ISR로부터 제외된다.



(음..그러면 min.sync.replica=2로하게되면 메시지 손실을 방지할수 있지않을까?)
왜냐하면 리더가 고립되는 것이 더 큰 메시지손실이 발생한다.
만약 최소 두개의 레플리카가 데이터를 받지 않았다면 exception을 던져 was측에서 실패로그 혹은 실패를 몽고디비에 저장한다.)
실험해 봐야 할 것은, 
mongodb ,Es 저장 vs 카프카 min.insync.replica = 2인 케이스



Message loss due to a fail-over as a result of a node failure with acks=1 was surprisingly low and we’ll see what affect slowing down the network has on that number. The biggest danger are network partitions with acks=1 due to the short window of split brain where a partition can have two leaders

가장 큰문제는 리더가 고립되고, 그 결과 새로운 리더가 선출될때 리더가 2개가 되면서 데이터 손실이 가장 크게 발생한다.
그러므로 데이터 손실을 발생을 100프로 막기위해서는 acks=all이 좋지만 이 경우는 성능이 너무 안좋고

그래서 acks=all 에 min.insync.replicas=2로 설정해
최소 2개의 브로커가 데이터를 저장한 경우 응답을 프로듀서에 보내는 것이 안전하다고 생각한다.

실제 운영환경에서 브로커 노드 2개가 동시에 다운되는 일은 거의 발생하지 않습니다. 그래서 Replication Factor를 3으로 운영하시고, 안정적인 구현을 위해서는 min.insync.replicas는 2로 설정하는 것이 가장 바람직하다고 생각된다.

댓글

이 블로그의 인기 게시물

(네트워크)폴링방식 vs 롱 폴링방식

(ElasticSearch) 결과에서 순서 정렬

(18장) WebSocekt과 STOMP를 사용하여 메시징하기