2016년 과거에 전반적인 데이터 부서의 업무 상황과 현재는 어떻게 진행하고 있는지 알아보고자 한다.
아무래도 streaming data를 위주로 분석 등을 진행하고 있는 현재, kafka의 중요성이 대두되고 있으므로 아래 다루고 있는 금일 학습 내용은 kafka 도입 이전과 이후의 변화 과정으로 보면 될 것 같다.
crontab -> Pinterest의 Pinball (Airflow 가 현재 대표적)
데이터 복사 방식 -> 중요 프로세스 개발 (B2B, SLA 설정 및 KPI 계산)
추천엔진 기반 score는 대개 여러 모델을 결합한 앙상블 구조로써 계산된다.
score의 변화를 살펴보면 결국엔 극단적이거나 비정상적인 관측값 뒤에 더 일반적인 또는 평균적인 관측값이 뒤따를 가능성이 높아지게 된다. 따라서 평균으로 회귀되는 현상이 발견.
현재의 경우 실시간 데이터 처리 기반 추천 계산 가능 ex) google - page rank 등의 등장
-> kafka 도입으로 기존 batch 처리에서 실시간 처리 가능토록 처리!
-> 수많은 로그 데이터로부터 logstach등의 툴을 이용해 producer로부터 생성되는 데이터를 읽어들여 모든 사용자 이벤트 데이터를 모두 먼저 kafka에 저장하고 이후 S3, Spark Streaming에 존재하는 다수의 Consumer가 데이터를 읽어 처리하는 구조ML 추천모델 개발
1. Hadoop cluster 도입해 빅데이터 batch 단위 처리 (Hive, UDF로 event data 처리)
2. Nginx (웹서버들 앞단에 load balancer로 사용되며 동시에 요청을 로그하는데 사용)
-> 보통 로그를 logstach등 툴을 사용해 HDFS, kafka로 푸시
3. 모델 배포 프로세싱 과정 (대부분의 DS : 통계 지표가 잘 되어있는 R로 모델개발했던 문제 발생) -> 현재는 Python 모델 개발 多
4. 시간이 지남에 따라 train 데이터와 실제 환경이 변화하며 모델 성능이 떨어지는 현상 발생 (data drift) -> 주기적인 ML 모델 빌딩 필요
DevOps
- 개발자가 만든 코드 시스템에 반영하는 CI/CD 진행
- 시스템 모니터링, 이슈 감지 시 escalation 프로세스 수행 (on-call 프로세스)
MLOps
- ML 모델 대상으로 CI/CD 진행
- 주기적인 CT (모델 빌딩) & CD
- 모델 서빙 환경, 모델 성능 저하 모니터링해 escalation 프로세스 수행
-> Latency 중요, data drift 모니터링
전체적인 실시간 추천 엔진 아키텍처를 살펴보면 다음과 같다.
1. S3, Redshift 등의 클라우드 스토리지, DW, 사용자 이벤트 데이터가 실시간으로 처리되어 저장되는 kafka로 부터 spark를 통해 batch 및 streaming 처리를 진행하여 DB에 저장한 후 ML model에 입력하여 실시간으로 추천을 위한 계산을 진행한다.
2. 이후 웹서버 이전 Nginx를 활용해 로드밸런싱을 진행한 후 추천 계산에 사용한 ML 모델 역시 DB에 저장함으로써 추후 data drift 모니터링, 주기적인 모델 빌딩을 진행한다.
✅ Avro
- Row-based binary 포맷 (Latency 중요한 경우)
- parquet은 column-based이기에 spark, DW 등 데이터 분석용으로 배치 쿼리 수행 시에 적합
- Avro의 경우 데이터 송수신, 스키마 변경 감지 등 streaming data 처리 포맷으로 최적
어제 학습을 진행하며 배웠던 kafka에서 내가 생각하기에 가장 중요한 부분은 backpressure이다. 물론 kafka 기능 자체를 구현하는 것도 중요하다.
하지만, 스트리밍 데이터 처리 역시 데이터 유실을 방지해야 하기에 consumer에서 데이터를 읽는 속도가 producer에서 읽고 저장하는 속도보다 빨라야 한다는 부분.-> 그 이유는 간단하다. 고속도로를 예시로 들어본다면 들어오는 차량의 수, 속도에 비해 고속도로를 빠져나가는 차량의 수, 속도가 낮다면, 과부하의 문제가 발생하게 되고 이를 kafka에 비유를 한다면 네트워크, 메모리, 디스크 문제로 이어지게 된다.
내가 궁금했던 내용은 해결방법에 구체성이다. 물론 강의로 학습한 것에 따르면 메세지 큐라든지 추가적인 메모리 버퍼를 사용해 해결한다고 하지만 이 역시 언젠가는 버퍼 용량 초과로 인해 backpressure가 다시 발생하게 될 것이다.
그렇다면 매번 버퍼를 추가해주어야 하는 것인가? 하는 의문점에 대해 이것저것 찾아본 결과, 크게 요약하면 다음과 같다.
1. 버퍼 용량 조정 (kafka cluster 수정 - server.properties, log.segement.bytes 등의 파라미터 수정)
2. consumer group modify
3. producer 측에서 데이터 저장 속도 제어
4. 디스크 용량 증가위와 같은 여러 대안책으로 backpressure를 보다 안정적으로 감안하며 실시간 스트리밍 데이터를 처리할 수 있다.
위 내용을 요약하면 뭐 추가적으로 fluentbit라는 툴이 또 있는 것으로 확인됌.