ML model 학습을 위한 kinesis streams의 데이터 처리방안

2020-09-11

.

Data_Engineering_TIL(20200911)

AWS 사용자모임 게시판 글을 읽고 배운 내용을 정리하였습니다.

해당 게시판글 URL : https://awskrug.slack.com/archives/C3D5K9LHY/p1599739266033200

# 해당 게시판글 요약

질문내용 :

kinesis streams의 데이터를 계속 rds 로 insert 하고 싶은데 어떤 방법들이 있는지 알고 싶음

kinesis streams의 이벤트 데이터를 ML prediction의 feature 로 활용하려는 의도

feature 는 예를 들어 [유저의 직전 5분 간 A 이벤트 수] 같은 것들임

방안 1 : Kinesis streams –> lambda –> RDS(또는 Redshift)

단, Error 나면 재기동하는 람다의 특성상 중복데이터 발생가능성이 있음.

다만 Lambda에서 DB connection을 여는 것 자체가 anti-pattern 중 하나임 (Lambda는 떴다 내려갔다 하므로 connection pool 관리가 전혀 안되기 때문에) 중간에 DB proxy를 붙여서 delegation 하는 것이 좋을것으로 판단됨

그리고 Kinesis - Firehose 를 썼을 때 데이터 중복에 관해선 사실 거의 중복될 일이 없을것으로 판단됨. 중복이 일어날 만한 point는 Lambda invocation이 실패해서 여러 번 retry 하는 경우인데 정상적인 경우라면 invocation이 실패할 일이 잘 없는편임. 만약 AWS 차원의 문제라면 그정도는 허용해주는 것이 오히려 속 편할 것임. 만약 한 점의 오차라도 허용할 수 없다고 하면 (예를 들어 주문같이 한 건의 영향이 큰 경우) 각 로그를 식별할 수 있는 txid 같은 것을 만들어서 RDB insert 할 때 활용하면 됨. (key constraint에 걸리도록) 이러한 처리가 없다면 사실 sink가 RDS가 아니어도 중복 문제는 피할 수 없음. 오히려 중복 문제를 해결하기 가장 좋은 곳이 RDB라고 생각됨. 인프라 차원에서 중복을 막을 수 있기 때문임. ES, Dynamo 등 NoSQL로 가는 순간 중복 데이터 식별이 더 어려울수도 있음.

방안 2 : Kinesis streams –> lambda –> DynamoDB

데이터의 관리나 후가공, 사용성 측면에서 RDS보다 더 나은 결정일 수 있음

quick + serverless 로 하겠다 하면 Dynamo

다만 Dynamo로 NoSQL을 잘 쓰려면 처음 설계가 매우매우 중요함

방안 3 : Kinesis streams –> lambda –> Elasticsearch

all-rounder 지만 schema 관리가 필요함. 분석 도구와도 잘 붙고 cluster 구성도 되는 장점이 있음.

schema change가 빈번하고 예측하기 어려울 거 같으면 좋은 옵션임

방안 4 : kinsis streams –> kinesis firehose –> s3 –> glue

NRT가 아닌 n분 이상의 gap을 허락할 수 있다면 그냥 S3 (+Glue) 에 적재하고 Athena를 통해 원하는 source로 넣어주는 방법도 있음

결국 데이터를 메모리로 로드해야 할거 같은데 s3(꼭 s3는 아니더라도 filestorage로)로 보내는게 좋은 판단일 수 있음. s3에 yyyymmdd 같이 파티셔닝 해서 parquet파일로 떨구고 한 다음에 파일로 불러오는 방법도 있음

# 해당 게시판글 원문

질문자 : kinesis streams의 데이터를 계속 rds 로 insert 하고 싶은데 어떤 방법들이 있을까요? firehose의 destination 중 rds 는 없네요…

답변자 a : 꼭 RDS에 너어야할 이유가 있나요? RDS에 넣으려면 람다 프로그램으로 넣어주시면 될것같은데요. 중복데이터가 생길거를 고려해서 분석하셔야 합니다. redshift, dynamo db에 넣는것이 좀더 안정적일 수 있습니다. 데이터량이 많다면 특히 dynamo db이고요 near realtime분석을 원하시면 es서비스가 맞을 거라 생각이 듭니다.

질문자 : 아하~ kinesis data stream 의 이벤트 데이터를 ML 추론의 feature 로 활용하려고 합니다. feature 는 예를 들어 [유저의 직전 5분 간 A 이벤트 수] 같은 것들이 될 것 같은데요. (near realtime + 유저 별 직전 수 hours 정도의 통계치) redshift = 빈도가 낮은 복잡하고 무거운 쿼리 / rds = 빈도가 잦은 가벼운 쿼리 정도로 구분하여 이해하고 있어서 이 use case 에는 후자가 맞지 않을까 생각했습니다. dynamodb / es 는 경험이 없어서 판단이 잘 안 서네요! 답변자님이 보시기에는 이 use case 에는 어떤 게 적당할 것 같으세요?

답변자 a : 우선 producer 입장에서 보면 rds에 저장을 하려면 lambda를 사용해서 저장을 해야 하고 전에 이야기 한것처럼 이것은 lambda의 특성(에러나면 재기동)이 있어 중복제거가 필요합니다. 다른 repository 서비스도 당연히 확인을 해야되겠지요. 저장과 잣은 짧은 조회면으로 보면 dynamo / es 가 좋을 듯합니다. ML추론을 어디서 돌리냐에 따라서 편한 서비스로 정하는 편이 좋을 듯합니다. 조금 시간적 갭이 허락한다면 glue 에 테이블을 정의하고 그곳에 저장하는것도 비용저렴하게 분석할 수 있는 방법이라고 생각합니다. 길어야 5분정도의 갭이 있을 겁니다.

답변자 b : AWS Lambda가 Kinesis에 대해서 이벤트 소스Batch 가 가능합니다.

https://aws.amazon.com/ko/about-aws/whats-new/2019/09/aws-lambda-now-supports-custom-batch-window-for-kinesis-and-dynamodb-event-sources/

배치 주기에 따라 다르겠지만, Lambda, Fargate, EC2 등을 이용해서 배치작업을 돌려서 RDS로 저장 가능합니다.

답변자 c : 조심스럽지만 저도 이 case는 rdb보다는 nosql이 데이터의 관리나 후가공, 사용성 측면에서 더 나은 결정이 되지 않을까 하는 의견을 드려봅니다.

질문자 : 의견 주신 세분 모두 감사드립니다! sink 를 어디에 하던 kinesis data stream 의 consumer 단에서 중복 제거는 기본적으로 신경 써줘야 하는 부분이겠네요! 조언 감사합니다. 질문자b님이 얘기해주신 lambda 의 event source batch 내용도 한번 확인해봐야겠네요. rds = SQL 에 대해서는 아는 내용이라 그림이 그려졌는데 / dynamo 와 es 가 데이터를 다룰 때 어떤 operation 들을 제공해주는지 몰라서 그림이 잘 안 그려지네요. 제가 dynamo 와 es 가 제공하는 operation 들에 대해 이해하는게 먼저겠습니다. 조언 감사드립니다! 그러고보니 NoSQL 솔루션으로는 DocumentDB 와 Keyspaces 도 있었던 것 같은데 함께 비교해보고 싶네요. https://aws.amazon.com/products/databases/ 에 간단히 정리된 테이블의 Use cases 를 봤을 때는 High-traffic 라는 키워드로는 DynamoDB / user profiles 라는 키워드로는 DocumentDB 가 관심이 가는군요. 답변자a님 glue 에 테이블을 정의한다 = S3 에 저장하고 Athena 로 쿼리한다라고 이해하면 될까요?

답변자 d : 데이터 특성에 따라 많이 다를 거 같지만 RDB로 표현하기 쉬운 데이터라면 RDS를 써도 될 거 같습니다. 저라면 위에 이미 언급된 방법인 Lambda에서 RDS로 직접 쏴주는 패턴을 선택할 것 같습니다. 다만 Lambda에서 DB connection을 여는 것 자체가 anti-pattern 중 하나여서 (Lambda는 떴다 내려갔다 하므로 connection pool 관리가 전혀 안 되니까요) 중간에 DB proxy를 붙여서 delegation 하는 것이 좋아보입니다. 그리고 Kinesis - Firehose 를 썼을 때 데이터 중복에 관해선 사실 거의 중복될 일이 없긴 합니다. 중복이 일어날 만한 point는 Lambda invocation이 실패해서 여러 번 retry 하는 경우인데 정상적인 경우라면 invocation이 실패할 일이 잘 없습니다. 만약 AWS 차원의 문제라면 그정도는 허용해주는 것이 오히려 속 편하기도 하고요. 만약 한 점의 오차라도 허용할 수 없다고 하면 (예를 들어 주문같이 한 건의 영향이 큰 경우) 각 로그를 식별할 수 있는 txid 같은 것을 만들어서 RDB insert 할 때 활용하면 됩니다. (key constraint에 걸리도록) 이러한 처리가 없다면 사실 sink가 RDS가 아니어도 중복 문제는 피할 수 없습니다. 오히려 중복 문제를 해결하기 가장 좋은 곳이 RDB라고 생각되네요. 인프라 차원에서 중복을 막을 수 있으니까요. ES, Dynamo 등 NoSQL로 가는 순간 중복 데이터 식별이 더 어려울 거 같습니다.

개인적인 경험으로는

RDS - 데이터를 관계형으로 표현할 수 있다면 best choice

ES - all-rounder 지만 schema 관리가 필요함. 그 외에는 딱히 단점을 모르겠네요. 분석 도구와도 잘 붙고 cluster 구성도 되는 장점이 있음

DynamoDB - 관리할 게 RCU, WCU 밖에 없긴 한데 그만큼 비쌉니다.

타 인프라 (예를 들어 비슷한 use case를 지닌 ElastiCache) 와 비슷한 성능을 내기 위해선 2-3배의 가격을 지불해야 합니다. 이런 cost 조정 때문에 불필요한 리소스도 들어가고요. 또 적절한 성능을 내기 위해선 GSI, LSI 등 인덱스 관리도 신경을 써줘야 합니다.

결론은 저라면 RDB와 fit이 맞으면 RDS (혹은 Aurora) 를, schema change가 빈번하고 예측하기 어려울 거 같으면 ES를, quick + serverless 로 하겠다 하면 Dynamo를 쓸 거 같습니다. 다만 Dynamo로 NoSQL을 잘 쓰려면 처음 설계가 중요합니다. 또 위에 답변자a님께서 말씀하신대로 NRT가 아닌 n분 이상의 gap을 허락할 수 있다면 그냥 S3 (+Glue) 에 적재하고 Athena를 통해 원하는 source로 넣어주는 방법도 있습니다. 저는 이런 방법도 즐겨 씁니다.

답변자 e : ml 모델의 feature로 사용하시는거면, model fit하는 코드에서 결국 데이터를 메모리로 로드해야 할거 같은데 s3(꼭 s3는 아니더라도 filestorage로)로 보내는게 좋지 않나요? 비슷한 일을 했었는데 처음엔 dynamodb의 key로 query 했다가 설계미스라고 생각해서 s3에 yyyymmdd 같이 파티셔닝 해서 parquet파일로 떨구고 한 다음에 파일로 불러오는게 편했던 경험이 있습니다