Data Engineering/spark

kafka 와 spark stream의 데이터 처리 방식

quantapia 2018. 9. 11. 16:08

나는 exactly once를 구현했다. 무슨 뜻이냐면...


『데이터는 정확히 한번 처리된다』 


당연히 데이터가 여러번 처리되면 안되겠지..


Spark Streaming는 처음에 Receiver를 이용하여 Kafka에 초기에 한번 접속 후 

데이터를 받아오는 구조로 설계되었다.


그 후에 복구를 위해 WAL 기능이 추가되었는데 



save image




이게 문제가 되는게 Receiver가 데이터를 가져오자마자 WAL에 저장하고 데이터 처리 도중에 죽었다면 Spark Streaming은 기동 시 WAL 에서 데이터를 꺼내서 처리하고 Kafka는 아까 읽었던 부분부터 Read Offset을 다시 수행한다. 


데이터가 중복된다는 뜻이지.


이걸 방지하기 위해 Kafka Direct API를 제공하는데 메카니즘은 이렇다.


save image



Offset 관리를 일관화 시키므로 데이터 중복 이슈를 없앴다.



여기서 주의할 게 최대 처리율 설정을 해줘야한다.


Kafka Direct API를 사용할 때 최대 처리율을 지정하는 옵션은

spark.streaming.kafka.maxRatePerPartition(Record) 이다. 


이 설정은 파티션당 초당 처리량이라는 점에 주의 해야한다. 

배치 간격이 10초이고 최대 처리율이 1000이고, 파티션 수가 4개라면 데이터는 최대 4 * 1000 * 10 = 40,000만큼의 Record를 받아온다.


최대 처리율을 설정하지 않으면 Spark Streaming을 중단했다가 재시작할 때, 그동안 처리하지 않고 쌓인 데이터를 한꺼번에 받아와서 처리하려고 한다.


배치 간격 동안 충분히 처리할 수 있는 데이터 양이라면 문제가 없지만, 중단 시간이 길어질수록 

데이터 양은 많아지기 때문에 배치 간격 내에 처리하기 어려워지고 지연시간이 증가하거나 

메모리 부족이 발생한다. (OOM을 만날 것이다!!)


중단과 재시작에서 설명하였듯이 재시작시 초기 배치는 시간이 더 걸리기 때문에, 안심하고 재시작을 자유롭게 하려면 최대 처리율을 설정하는 것이 좋다.


나는 노가다를 통해 밀리지 않는 구간인 300,000만 Record로 설정했다.