2018년 10월 25일 목요일

Kafka 간단 개념 정리.

참고로 Kafka 안써봄.. ㅠㅠ

카프카는 1)영속적, 2)분산, 3)분할, 4)복제되는 대량의 데이터를 수집하기 위한 메시징 시스템이다. 카프카는 데이터 소스와 데이터 처리기 사이에서 버퍼 역할을 해주는데 이는 스트림 처리에서 꼭 필요한 요소다. 참고로 링크드인에서 데이터 흐름을 한곳으로 모으기 위해 만들었다고 한다. 분산 시스템이기 때문에 한 두개 장비가 망가져도 잘 동작하며 Queue를 기본으로 하는 메시징 시스템이기 때문에 데이터의 순서를 보장해준다. 카프카는 프로듀서, 컨슈머, 브로커로 구성된다. 프로듀서는 데이터를 만들어 넣는 역할, 컨슈머는 데이터를 꺼내 쓰는 역할, 그리고 브로커는 프로듀서와 컨슈머의 메시지를 관리하는 클러스터 서버의 역할을 수행한다. (DDS와 유사한 형태의 Publish/Subscribe 모델.) 분산 코디네이터로는 주키퍼를 쓴다.

카프카는 높은 성능, 다양한 언어를 지원하기 위해 클라이언트와 서버 간 통신으로 TCP 프로토콜을 이용하며 카프카 브로커는 FIFO 형태의 토픽이라는 카테고리를 가지고 있다. 토픽은 Queue의 구조와 같다.. 각 메시지는 자신의 고유한 식별자인 인덱스를 가지고 있는데, 카프카에서는 이를 오프셋이라 한다. 각각의 컨슈머는 어디까지 읽었냐에 대한 오프셋을 관리하게 된다. 오프셋 관리만 잘하면 장애로 인해 예상치 못하게 중단되거나 운영 상의 이유로 언제든지 중단하여도, 안심하고 장애 처리나 업그레이드 같은 작업을 하고 재시작할 수 있다. 단, 중단된 시간이 길어지면, Kafka에서 버퍼링하며 저장할 수 있는 데이터 크기를 넘어설 수 있으므로 주의해야 한다. (근데 오프셋 관리가 어렵다고 함.)

기본적으로 토픽은 1개 이상의 파티션(물리적으로 분할된 Queue)을 가지고, 하나의 브로커나 다수의 브로커에 분산 배치될 수 있다. 토픽을 다수의 파티션에 나누어 여러 브로커에 분산 배치함으로 메시지 전송에 따른 부하를 분산시키는 구조다. 카프카는 영속성을 제공하기 위해 파일 시스템에 메시지를 저장한다. 데이터를 파일에 쓰면서도 메모리 대비 성능을 잃지 않는 것이 특징이다. OS 페이지 캐싱을 통해 read()에 의한 블락 없이 직접 매핑된 주 메모리를 참조하여 파일에 데이터를 기록하면서도 빠른 성능을 보장한다. 또한 Zero Copy 기법을 채택한 Java nio의 FileChannel.transferTo()를 통해 메모리의 데이터를 커널 레벨에서 소켓으로 바로 넘겨 버리는 방식으로 성능을 높이고 있다.

* OS 페이지 캐싱
주 메모리에 가능한 많은 파일을 미리 캐싱해서 실제 요청이 왔을 때 파일 Read 시간을 최소화 하는 기법.

결과적으로 메모리 사용을 최소화하는 구조이므로 GC에 의한 성능 감소를 예방한다. (자바 오브젝트의 메모리 오버헤드는 매우 높고, 종종 저장된 데이터의 크기보다 더 크게 부풀려진다. 자바 GC는 힙 안의 데이터가 증가할수록 점점 더 다루기 어렵고 느려지는 특성이 있다.)

각 파티션은 설정한 서버의 숫자만큼 복제되고, 각 파티션은 카프카 클러스터에 분산되 저장된다. 파티션은 Leader 역할을 하는 하나의 서버와, 0개 이상의 Follower 서버를 갖는데 Follower가 Leader를 복제하는 동안, Leader는 파티션을 위한 모든 읽기와 쓰기 요청을 처리한다. 복제는 파티션 단위로 처리되는데 복제 계수가 3이면 1개의 Leader, 2개의 Follower 구성을 뜻한다. 복제 계수는 브로커 개수 이상으로 설정할 수 없다. (한 서버에 동일한 파일을 저장할 필요가 없기 때문.) 사용자의 모든 요청은 리더 파티션이 담당하며, 카프카의 복제는 가용성(Availability)을 높일 뿐, 성능 향상에 영향을 주진 않는다. 카프카는 프로듀서가 특정 토픽 파티션에 전송한 데이터의 순서를 보장한다. 그리고 컨슈머는 저장된 순서대로 메시지를 처리하게 된다. 카프카는 메시지의 순서와 메시지가 단한번 소비되는 것을 보장하지만 처리 순서는 하나의 파티션에 대해서만 보장한다. 여러 개의 파티션으로 분산된 데이터의 순서는 보장하지 않는다는 뜻이다. 게다가 비동기 방식이라 클러스터 구성이 복잡해지면 골때리는 경우가 제법 생기는 듯 하다.

* 주키퍼
주키퍼 = 분산 코디네이터. 분산 코디네이터라고 하면 뭔가 어렵게 다가온다. 클러스터 구성원 간의 데이터 공유를 위한 데이터 저장 기법(기술)이라 생각하면 조금 편해지려나.. 데이터를 디렉터리 구조로 저장한다. 데이터를 저장할 때 해당 세션이 유효한 동안 데이터가 저장되는 Ephemeral Node라는 것이 존재하고, 데이터를 저장하는 순서에 따라 자동으로 일련번호가 붙는 Sequence Node라는 것이 존재한다. 이러한 기능이 주키퍼의 전부. 이러한 기능을 가지고 입맛에 맞게 확장해서 사용하면 된다.
(입맛? 서버 투입/제거 시에 대한 이벤트 처리, 분산 환경에서 서버들 간의 정보 공유, 서버 모니터링, 분산 락 처리, 장애 상황 판단, 분산 시스템에서 리더 선출, 클러스터 멤버십 관리를 통한 데이터 변경 통지..)

주키퍼는 일반적으로 3대 이상을 사용하며 홀수로 구성한다. 서버 간의 데이터 불일치가 발생하면 보정이 필요한데 이떄 과반수의 룰을 적용하기 때문이다. 주키퍼 서버는 Leader와 Follower로 구성되어 있다. 서버들끼리 자동으로 Leader를 선정하며 모든 데이터 저장을 주도한다. 클라이언트가 Follower 서버로 데이터 저장을 시도한다면
Client > Server(Follower) > Server(Leader) > 나머지 Server(Follower) 순으로 데이터를 전달한다. 저장을 마치면 클라이언트에게 성공/실패를 동기 방식으로 알려준다. 즉 모든 주키퍼 서버는 동일한 데이터를 가지고 있고, 클라이언트가 어떤 서버에 연결되어 데이터를 가져가더라도 동일한 데이터를 가져가게 된다. 주키퍼에 잦은 변경이 일어나는 애플리케이션 성격의 데이터를 저장하는 것을 옳지 않으며 Read:Write 비율이 10:1 이상이 권장된다.

Apache ZooKeeper is an effort to develop and maintain an open-source server which enables highly reliable distributed coordination. // Zookeeper is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services. 

읽어볼만한 국문 링크.
1] http://www.chidoo.me/index.php/2016/11/06/building-a-messaging-system-with-kafka/
2] http://readme.skplanet.com/?p=12465

댓글 없음:

댓글 쓰기