6

Amazon Kinesis Streams documentation에 따르면 레코드가 여러 번 전달 될 수 있습니다.Amazon Kinesis Record duplicates는 어떻게 처리합니까?

모든 레코드를 한 번만 처리하는 유일한 방법은 무결성 검사 (예 : DynamoDB, Elasticache 또는 MySQL/PostgreSQL)를 지원하는 데이터베이스에 임시 레코드를 저장하거나 각 Kinesis 샤드의 RecordId를 체크 포인트하는 것입니다.

더 효율적이고 중복 된 방법을 알고 계십니까?

답변

6

우리는 정확히 문제가 있었다 . 우리의 경우 우리는 생산자가 각 메시지를 정확하게 한 번 전송했는지 여부를 확신 할 수 없었습니다. 따라서 수신 된 각 레코드에 대해 MD5를 즉석에서 계산하고 영구 저장 장치의 형태로 표시되는지 여부를 확인했지만 실제로 사용할 저장 장치는 무엇입니까? 가장 까다로운 비트.

우선 우리는 사소한 관계형 데이터베이스를 시도했지만 키네시스를 거치는 데이터의 양이 상당히 중요했기 때문에 이것은 읽기가 무거웠지만 쓰기가 힘든 경우이므로 시스템 전체의 주요 병목 현상이되었습니다. .

고유 메시지마다 MD5를 저장하는 DynamoDB 테이블을 갖게되었습니다. 우리가 가진 이슈는 메시지를 지우는 것이 그렇게 쉽지 않았기 때문입니다. 우리 테이블에는 파티션과 정렬 키가 포함되어 있지만 DynamoDB는 주어진 파티션 키를 가진 모든 레코드를 삭제할 수 없지만, 키 값 정렬 (시간과 용량 낭비). 불행히도 우리는 테이블 전체를 한 번만 놓아야했습니다. 차선책은 메시지 식별자를 저장하는 DynamoDB 테이블을 정기적으로 회전시키는 것입니다.

그러나 최근 DynamoDB는 매우 편리한 기능 (Time To Live)을 도입했습니다. 즉, 레코드 당 자동 만료 기능을 활성화하여 테이블의 크기를 제어 할 수 있습니다. 이러한 의미에서 DynamoDB는 ElastiCache와 매우 유사하지만 ElastiCache (적어도 Memcached 클러스터)는 훨씬 덜 내구성이 있습니다. 이중화가 없으며 작동 또는 실패의 규모가 큰 경우 종료 된 노드에있는 모든 데이터가 손실됩니다.

+1

안녕하세요 드미트리. 여기에 설명 된 JustGiving 인프라와 비슷한 것을 사용하여 여러 벤치 마크를 실행했습니다. https://aws.amazon.com/blogs/compute/serverless-cross-account-stream-replication-using-aws-lambda -amazon-dynamodb-and-amazon-kinesis-firehose/왜 DDB 테이블에 Shardid + SequenceNumber를 사용하는 대신 MD5 체크섬을 계산 했습니까? – Antonio

+2

안녕하세요 @Antonio. 우리의 경우에는 제작자가 동일한 메시지를 게시 할 가능성이 있습니다 여러 번. 키네스는 어쨌든 여러 메시지를 다른 메시지로 간주합니다. (단순히 제작자가 2 번 이상 게시했기 때문입니다.) 모든 메시지가 고유해야한다는 것을 알았으므로 단순히 md5가 가진 메시지를 무시했습니다. 또한 md5는 생산자가 계산하여 cosumers에 대한 계산 시간을 절약 해주었습니다. (키네시스를 거치면서 상대적으로 많은 양의 데이터가 제공됨) –

+0

그냥 던지기를 원했습니다 - AWS는 제작자는 오류 사례로 인해 동일한 기록을 자연스럽게 여러 번 생성 할 수 있으며, 일반적으로 여러 소비자가 동일한 기록을 가져올 수 있습니다. 지금 우리 시스템에서도이 문제를 다루고 있습니다. 우리는 elasticsearch를 사용합니다. 그리고 현재 계획은 같은 레코드가 동시에 업데이트되지 않도록하기 위해 버전 관리에 내장 된 탄성체를 사용하고 레코드 자체에 레코드에 적용된 최근 이벤트 목록을 기록하는 것입니다. – genexp

7

언급 한 사항은 "적어도 한 번"접근 방식을 사용하는 모든 대기열 시스템의 일반적인 문제입니다. 또한 대기열 시스템, 생산자 및 고객 모두가 동일한 메시지를 여러 번 처리 할 수 ​​있습니다 (ReadTimeout 오류 등으로 인해). Kinesis와 Kafka는 모두이 패러다임을 사용합니다. 불행히도 쉬운 대답은 아닙니다.

엄격한 트랜잭션 방식으로 "정확히 한 번"메시지 대기열을 사용해 볼 수도 있습니다. 예를 들어 AWS SQS가 수행하는 작업은 https://aws.amazon.com/about-aws/whats-new/2016/11/amazon-sqs-introduces-fifo-queues-with-exactly-once-processing-and-lower-prices-for-standard-queues/입니다. SQS 처리량은 키네시스보다 훨씬 작습니다.

문제를 해결하려면 응용 프로그램 도메인을 알고 제안 된 (데이터베이스 검사) 것과 같이 내부적으로 해결해야합니다. 특히 외부 서비스와 통신 할 때 (예를 들어 이메일 서버), 이중 처리를 방지하기 위해 작업 상태를 복구 할 수 있어야합니다 (전자 메일 서버 예제에서 이중 전송으로 인해 받는 사람의 사서함에 동일한 게시물).

다음 개념도 참조하십시오.

  1. 에서-최소 한 번 배달 : http://www.cloudcomputingpatterns.org/at_least_once_delivery/
  2. 정확히 한 번만 배달 : http://www.cloudcomputingpatterns.org/exactly_once_delivery/
  3. 멱등 프로세서 : 모바일 앱에 대한 원격 측정 시스템을 구축 할 때 http://www.cloudcomputingpatterns.org/idempotent_processor/
+0

답장을 보내 주셔서 감사합니다. 높은 처리량으로 인해 SQS를 사용할 수 없습니다. 높은 처리량은 다른 내구성 스토리지 (Mysql/PgSQL/Aurora/ElasticSearch/DynamoDB)를 사용하여 여러 솔루션을 벤치마킹하는 이유이기도합니다. 이벤트 ID를 임시 저장하는 가장 좋은 방법은 Redis이지만 ElastiCache는 데이터 내구성을 부여 할 수 없습니다. 그것이 내가 그것을하는 대체 방법을 찾고 있었던 이유입니다. – Antonio

+1

Redis는 엄격한 tx 추적을 허용하지만 단일 노드이며 RDS가 너무 느립니다. DynamoDB가 유일한 PaaS 솔루션 인 것 같습니다. 그러나 EC2 인스턴스를 관리하려면 Hazelcast 또는 VoltDB와 같은 메모리 기반 클러스터 솔루션 (많은 r3 노드에서)을 시도 할 수 있습니까? – az3

+0

인 메모리 데이터베이스는 내구성이 없습니다. Hazelcast 클러스터가 실패하면 이미 처리 한 메시지를 이해할 수 없습니다. : – Antonio