2014-04-24 3 views
21

Amazon SQS에서 중복 메시지를 방지하는 가장 좋은 방법은 무엇입니까? 크롤링 대기중인 도메인의 SQS가 있습니다. SQS에 새 도메인을 추가하기 전에 저장된 데이터를 검사하여 중복을 방지하기 위해 최근에 크롤링되었는지 확인합니다.중복 된 SQS 메시지를 방지하려면 어떻게해야합니까?

아직 크롤링되지 않은 도메인에 문제가 있습니다. 예를 들어 큐에 크롤링되지 않은 도메인이 1000 개있는 경우 링크를 다시 추가 할 수 있습니다. 내 SQS가 대다수 인 수십만 개의 메시지로 팽창합니다.

어떻게 방지합니까? 대기열에서 모든 중복을 제거하는 방법이 있습니까? 아니면 메시지를 추가하기 전에 대기열을 검색하는 방법이 있습니까? 나는 이것이 SQS를 가진 사람이 경험 했어야하는 문제라고 생각한다.

내가 볼 수있는 한 가지 옵션은 도메인이 SQS에 추가되기 전에 일부 데이터를 저장하는 경우입니다. 그러나 데이터를 두 번 저장해야한다면 처음에는 SQS 사용의 요점을 망칠 수 있습니다.

+0

[SQS 대기열에서 많은 소비자 사용하기] (http://stackoverflow.com/questions/37472129/using-many-consumers-in-sqs-queue) – Krease

+1

AWS는 이제 [fifo queues] (http : //docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/FIFO-queues.html)에서 "정확히 한 번만 처리되지만 초당 300 회의 트랜잭션으로 제한됩니다." – bishop

답변

15

다른 답변으로 언급 한 것처럼 SQS에서 오는 중복 메시지는 방지 할 수 없습니다.

대부분의 경우 메시지는 소비자 중 한 사람에게 한 번 전달되지만 어떤 경우에는 번으로 중복됩니다.

이 질문에 대한 쉬운 대답은 생각하지 않습니다. 중복을 피할 수있는 적절한 아키텍처가 필요하기 때문에 자연에서 멱등수를 의미하기 때문입니다.

분산 아키텍처의 모든 작업자가 멱등 (idempotent)이라면 복제에 대해 걱정할 필요가 없기 때문에 쉽습니다. 그러나 현실적으로는 그런 종류의 환경이 존재하지 않습니다. 어딘가에 무언가 그것을 처리 할 수 ​​없을 것입니다.

현재이 문제를 해결해야하는 프로젝트를 진행하고 있으며이를 처리 할 수있는 방법을 제안합니다. 내 생각을 공유하는 것이 다른 사람들에게 도움이 될 것이라고 생각했습니다. 그리고 내 사고에 대한 피드백을 얻는 것이 좋은 장소 일 수 있습니다.

사실 저장소

그것은 그들이 이론적으로 영향을받는 모든 다운 스트림 시스템에서 같은 상태를 재현 재생할 수 있습니다 사실을 수집 할 수 있도록 서비스를 개발하는 아주 좋은 생각이다.

예를 들어 주식 거래 플랫폼 용 메시지 브로커를 구축한다고 가정 해 보겠습니다. (나는 전에 이런 프로젝트를 실제로 해왔지만, 그것은 끔찍했지만 좋은 학습 경험이었습니다.이제)

의가 들어올 무역, 그리고에 관심이 3 개 시스템이 있다고 가정 해 봅시다 :

  1. 모든 거래와 대조
  2. 시스템을 업데이트 상태를 유지해야하는 오래된 학교 메인 프레임 FTP 서버
  3. 거래를 기록하고, 새 주인이 조금 복잡의

에게 주식을 재 할당 서비스에 파트너와 공유, 나는 케이 지금은,하지만 그 아이디어는 하나의 메시지 (사실)가 들어오고 있으며, 여러 가지 분산 된 다운 스트림 효과를 가지고 있습니다.

이제 브로커에 들어오는 모든 거래를 기록한 사실 저장소를 유지한다고 가정 해 봅시다. 그리고 3 명의 모든 다운 스트림 서비스 소유자는 지난 3 일간 모든 데이터를 잃어 버렸다고 말합니다. FTP 다운로드는 3 일 뒤이고, 메인 프레임은 3 일 뒤이고, 모든 거래는 3 일 뒤에 있습니다.

사실 저장소가 있으므로 이론적으로 이러한 메시지를 특정 시간부터 특정 시간까지 재생할 수 있습니다. 이 예에서는 3 일 전부터 지금까지입니다. 그리고 다운 스트림 서비스가 포착 될 수 있습니다.

이 예제는 조금 위에 보일 수도 있지만, 매우 구체적인 것을 전달하려고합니다. 사실은 추적해야 할 중요한 것입니다. 왜냐하면 그것이 우리의 아키텍처에서 중복과 싸우기 위해 사용하기 때문입니다 .

팩트 저장소가 당신에게 CAP theorem, 일관성 및 가용성의 CA 부품을 제공하는 지속성 계층에 사실 저장소를 구현 제공 중복 메시지

에 도움이 어떻게, 다음을 수행 할 수 있습니다

대기열에서 메시지를 받자 마자 바로이 메시지를 이미 본 적이 있는지 여부와 사실이 잠겨 있는지 여부, 보류 중 상태인지 팩트 저장소에 체크인합니다. 필자의 경우 사실 저장소를 구현하기 위해 MongoDB를 사용할 것이지만, 다른 DB 기술이 이것을 처리 할 수 ​​있어야합니다.

사실이 아직 존재하지 않으면 보류 중 상태 및 잠금 만료 시간이있는 사실 저장소에 삽입됩니다. 이 작업은 두 번 발생하지 않기 때문에 원자 연산을 사용하여 수행해야합니다. 여기서 서비스의 idempotence을 보장합니다.

해피 경우 - 시간

팩트 저장소가 사실은 존재하지 않았다, 그리고 잠금이 만들어 졌는지를 말하는 당신의 서비스에 돌아 오면 대부분의 서비스는 작업의 수행을 시도 일이 발생 . 완료되면 은 SQS 메시지을 삭제하고 사실을 완료로 표시합니다.

중복 메시지

그래서 메시지를 통해 제공하고 중복이 아니다 때 발생합니다. 그러나 중복 메시지가 언제 들어 왔는지 살펴 보겠습니다. 서비스가이를 선택하고 팩트 저장소에 자물쇠로 레코드하도록 요청합니다. 팩트 저장소는 이미 존재한다는 것을 알려주고 잠겨 있습니다. 서비스가 메시지를 무시하고 건너 뜁니다!메시지 처리가 완료되면 다른 작업자가 대기열에서이 메시지를 삭제하고 다시 표시하지 않습니다.

재해 케이스 - 서비스가 가게에 처음으로 사실을 기록 할 때

그래서 무슨 일이 후 일정 기간 동안 잠금을 얻을 일이 드물게 발생하지만, 쓰러져서? 만약 SQS가 선택 되었다면 다시 SQS가 당신에게 메시지를 보여줄 것입니다. 서비스가 제한된 시간 동안 잠금을 유지하도록 팩트 스토어를 코딩하는 이유는 무엇입니까? 그것이 넘어지면 우리는 SQS가 메시지를 서비스 나 다른 인스턴스에 나중에 표시하여 해당 서비스가 사실을 상태 (실행)에 통합해야한다고 가정 할 수 있기를 원합니다.

+0

접근 방식을 공유해 주셔서 감사합니다 –

+0

비슷한 접근법을 채택하고 문제가 발생하면 문제 없습니다. 나는 도울 수 있을지도 모른다. – hendrikswan

+1

굉장한 해답! 약간의 단발 : ** Happy Case **에서 사실을 완료로 표시하고 SQS 메시지를 삭제 한 다음 삭제해야한다고 말합니다. 그런 다음 사실이 이미 완료되었다고 표시되면 메시지를 삭제하기 위해 ** 중복 메시지 ** 대/소문자를 업데이트하는 것이 좋습니다 (원래 처리기가 처리 할 때까지 기다리지 말 것). –

2

중복 메시지가 SQS 대기열에 게시되는 것을 방지하는 API 수준의 방법은 없습니다. 응용 프로그램 수준에서이 문제를 처리해야 할 필요가 있습니다.

DynamoDB 테이블을 사용하여 크롤링 대기중인 도메인 이름을 저장하고 예를 들어 DynamoDB에없는 경우에만 대기열에 추가 할 수 있습니다.

+2

하지만 그렇게한다면 SQS를 전혀 사용하지 않는 이유는 무엇입니까? 왜 응용 프로그램을 DynamoDB에서 곧바로 읽을 수 있습니까? 어쩌면 나는 SQS 사용에 대해 잘 이해하지 못했지만, 여전히 모든 데이터를 데이터베이스에 저장해야한다면, SQS가 그 가치와 중요성을 잃어 버리는 것처럼 느껴집니다. 나에게 SQS를 사용하려는 이유는 데이터베이스에 데이터를 쓸 필요가 없다는 것입니다. –

+1

이것은 아키텍처 결정입니다. SQS (또는 임의의 대기열 처리 시스템)는 애플리케이션 간의 비동기 통신을 허용하고 여러 메시지 생성자가 여러 생성자의 메시지를 사용하는 데 적합합니다. 예는 웹 계층과 일괄 처리 작업자간에 발생합니다. 데이터베이스는 이러한 통신 유형으로 설계되지 않았으므로 추가 작업이 필요합니다. 그러나 DB는 독립적 인 근로자 또는 앱간에 상태를 공유하는 데 능숙합니다. 귀하의 유스 케이스에서, 아마 DB가 충분합니다. –

2

SQS가 중복 된 메시지를 보내지 못하도록 방지 할 수 없기 때문에이 메시지를 사용자 측에서 구현해야합니다. 이를 수행하는 간단한 방법은 Apache Camel의 멱등하지 않은 소비자를 사용하는 것입니다. http://camel.apache.org/idempotent-consumer.html

관련 문제