2017-10-26 41 views
0

비 트랜잭션 환경에서 메시지 전달을 보장하는 방법은 무엇입니까? 레디 스 | | OtherMQ, 소비자가 ... 메시지가 처리를 계속 끌어 MQ - 트랜잭션이없고 가벼운 환경에서 메시지 전달을 보장하는 방법은 무엇입니까?

  • 0.05 %, 커밋, 데이터베이스에 ZeroMQ에 보내기 메시지를 작성 :

    • 정상 상황 : 예를 들어

      상황 : 데이터베이스에 쓰기, 커밋, 응용 프로그램이 죽습니다!, 메시지를 보내지 않았으며, 소비자가 메시지를 가져 오지 못했으며, 처리가 완료되지 않았습니다.

    이 상황에서 메시지를 보내지 않으려면 (메시지를 보내지 마십시오) 어떻게해야합니까?

    편집 : 메시지는 정확히 한 번 전달되어야합니다.

  • +0

    생산자가 전송할 때 "보낸"것으로 db에 메시지를 표시하고 시작할 때 "보내지 않은"메시지를 모두 가져 오지 않습니까? 보낸 메시지에 대한 정보를 저장할 수있는 다른 방법이 없습니다. – cassandrad

    +0

    @cassandrad 메시지가 MQserver로 전송 된 후 앱이 죽을 수 있지만 앱 표시 전에는 메시지가 db로 전송되었습니다. 다른 옵션 : db 트랜잭션과 동일한 메시지 (db 테이블)는 여전히 고객을 기다리고 있습니다. 커밋, 메시지 보내기, 소비자가 메시지를 가져 오면 소비자가해야 할 일은 메시지를 db로받은 것으로 표시하는 것입니다. 그러나이 방법은 고주파 메시지의 경우 느립니다. – weakleaf

    +0

    "그는 메시지가 MQserver로 전송 된 후 앱이 죽을 수 있지만 앱 표시 전에는 메시지가 db로 전송되었습니다." 전혀 문제가 없습니다. 앱을 시동하면 메시지가 다시 전송됩니다. 배달 옵션이 정확히 한 번만 지정되어 있다고 지정하지 않았습니다. – cassandrad

    답변

    1

    이 시나리오에서는 2 개의 공유 리소스 (데이터베이스 및 큐)가 있고 이들을 함께 처리하려고합니다. 메시지가 대기열로 전송 된 경우 데이터베이스를 커밋해야합니다. 성공적으로 전송되지 않으면 데이터베이스를 커밋하지 않고 그 반대도 마찬가지입니다. 이것은 단순히 2PC와 같은 글로벌 트랜잭션 메커니즘입니다. 그러나 글로벌 트랜잭션 메커니즘을 구현하는 것은 쉽지 않으며 비용도 많이 듭니다.

    일관성을 제공하기 위해 소비자 측에서 생산자 측면과 멱등 원함에 대한 전략을 하나 이상 구현하는 것이 좋습니다.

    생산자 측 데이터베이스에 메시지 테이블을 만들고 대기열로 보내기 전에이 테이블에 메시지를 저장해야합니다. 그런 다음 예약 된 스레드 (여기에는 처리량을 높이기 위해 여러 개의 스레드가있을 수 있지만 생성 된 순서대로 메시지를 사용해야하는 경우주의해야합니다.) 또는 큐에 보낼 수있는 다른 모든 메시지는 이미 전송 된 메시지는 다시 전송되지 않습니다. 그렇게해도 메시지가 두 번 이상 발송되는 경우가 있습니다 (예 : 메시지를 대기열로 보내고 전송 된 메시지를 표시하기 전에 애플리케이션이 다운 됨). 그러나 우리는 이미 적어도 한 번 이상 메시지를 큐에 보내길 원한다는 것을 의미하는 생산자 측 전략을 적어도 한 번 이상 구현하기를 원하기 때문에 문제가되지 않습니다.

    소비자가 제작자 측에서 두 번 이상 생성 된 동일한 메시지를 소비하지 못하게하려면 멱등하지 않은 소비자를 구현해야합니다. 간단하게 소비 된 메시지의 ID를 소비자 측의 데이터베이스 테이블에 저장하고 큐에서 오는 메시지를 처리하기 전에 이미 소비되었는지 확인할 수 있습니다. 이미 소비 된 경우이를 무시하고 다음 메시지를 가져와야합니다.

    물론 마이크로 서비스 환경에서 일관성을 유지하는 데있어 다른 옵션이 있습니다. 이 훌륭한 블로그 (https://www.nginx.com/blog/event-driven-data-management-microservices/)에서 다른 솔루션을 찾을 수 있습니다. 위에서 설명한 솔루션도이 블로그에 있습니다. 로컬 트랜잭션을 사용하여 이벤트 게시 섹션에서 찾을 수 있습니다.

    0

    여기에 간단한 방법이 있습니다.

    의 당신이 거래 있다고 가정하자 : DB에

    1. 쓰기 데이터
    2. ZMQ 보내 메시지를
    3. 보내는 확인했다 DB에
    4. 쓰기

    그래서 앱 충돌 동안 가정 그렇다면 마지막 메시지가 고객 대기열을 수신했는지 그리고 마지막 확인 (3 단계)없이 모든 메시지를 다시 시작한 후 다시 보내야하는지 여부를 알 수 없습니다.

    소비자에게 문제가되는 것은 가능하기 때문에 메시지를 두 번 받는다는 것입니다. 이 문제를 해결하기 위해 항상 증가하는 트랜잭션 ID를 각 메시지와 함께 보낼 수 있습니다. 소비자는 마지막 메시지의 트랜잭션 ID를 알아야합니다. 들어오는 메시지의 트랜잭션 ID가 마지막 메시지의 트랜잭션 ID보다 높지 않으면 메시지를 무시할 수 있습니다.

    이제 메시지 구조와 사용할 수있는 트랜잭션 ID를 수정할 수 있는지 여부가 궁금합니다.