마이크로 서비스에서 데이터를 동기화하는 올바른 방법은 무엇입니까?


19

저는 마이크로 서비스 아키텍처를 처음 접합니다. 우리는 적당한 크기의 웹 응용 프로그램을 가지고 있으며 현재 진행중인 모 놀리 식 시스템 대신 마이크로 서비스로 나누는 장단점을 평가하고 있습니다.

내가 이해하는 한, 마이크로 서비스 AB각각이 상대방이 가지고있는 데이터의 하위 집합에 의존하는 것을 고려 하십시오. A무언가 변경되었다고 메시지가 게시되면 해당 메시지 B를 사용하고 로컬 A정보 사본을 복제하여 B필요한 정보를 사용할 수 있습니다.

그러나 B다운 / 실패하면 잠시 후 다시 돌아옵니다. 중단 시간 동안 A두 개의 메시지를 더 게시했습니다. B로컬 A정보 사본을 업데이트하는 방법을 어떻게 알 수 있습니까?

물론 대기열 B의 유일한 소비자 인 A경우 온라인으로 돌아 오면 읽기를 시작할 수 있지만 해당 대기열의 다른 소비자가 있고 해당 메시지가 소비되면 어떻게 될까요?

보다 구체적인 예로, 마이크로 서비스가 다운 Users된 상태 에서 서비스의 이메일 주소가 업데이트 된 Billing경우, Billing마이크로 서비스가 다시 가동되면 이메일이 업데이트되었음을 ​​어떻게 알 수 있습니까?

마이크로 서비스가 다시 시작되면 "이봐 요, 내가 현재 모든 정보를 알려주세요"라는 방송을합니까?

일반적으로 데이터 동기화를위한 최상의 업계 관행은 무엇입니까?


1
가능할 때마다 피하십시오.
Telastyn

1
Orders알아야 Users합니까?
kdgregory

단지 예일뿐입니다. 두 가지를 원하는 것으로 바꾸십시오.
noblerare

팬 아웃 라우팅은 '다른 사람이 메시지를 사용합니다'문제를 해결합니다. 그러나 당신이 무엇을 성취하려고하는지 명확하지 않습니다.
Ewan

@Ewan 나는 내가 무엇을 묻고 있는지 더 잘 설명하기 위해 원래 게시물을 업데이트했습니다.
noblerare

답변:


5

"다른 모든 마이크로 서비스에 데이터를 푸시하는"아이디어에 도전 할 것입니다.

일반적으로 청구 서비스에 이메일 주소가 필요한 경우 특정 고객의 이메일 주소를 주소 서비스에 요청하기 만하면됩니다. 모든 주소 데이터의 사본을 보유 할 필요는 없으며 변경 사항이있을 경우에도 통보되지 않습니다. 최신 데이터에서 묻고 답을 얻습니다.


나는이 대답이 옳다고 생각합니다. 동기화와 관련된 많은 문제를 제거합니다. 사실, 다른 서비스가 정보 사본을 보관하고 동기화 문제가 있기 때문에 이러한 문제가있는 코드를 지금보고 있습니다.
DaveG

2
답변 주셔서 감사합니다. 그렇다면 왜 pub / sub 모델과 메시지 큐가 필요한가? "푸시"데이터 대신 "풀"하려고하면 서비스 대기 시간이 걱정됩니다.
noblerare

AFAIK, 펍 / 서브와 같이 변경 사항이있는 경우 서비스가 즉시 반응 할 필요는 없지만 때때로 데이터가 필요합니다. 그럼 그냥 잡아 당겨 대기 시간이 걱정되면 데이터를 캐시 할 수 있지만 데이터가 최신인지 알지 못하는 비용이 발생합니다. 파일이 큰 경우 무언가를 다시 가져 오기 전에 변경 사항이 있는지 물어볼 수도 있습니다.
J. Fabian Meier

이 솔루션은 종속 서비스를 밀접하게 연결하는 비용이 발생하므로 사용자 서비스를 사용할 수없는 경우 전자 메일 주소를 사용할 수 없습니다. 독립적으로 배포 가능하고 확장 가능하도록 서비스를 시작하려는 초기 아이디어 중 하나입니다. 모든 서비스가 캐시없이 또는 고 가용성을 보장하지 않고 서로 직접 통신하는 경우 하나의 시스템이 다운되면 모두 내려가
dukethrash

@dukethrash 그런 다음 가용성을 높이십시오.
J. Fabian Meier

5

좀 더 많은 연구를 한 후에, 나는 기사를 우연히 발견했습니다. 기사에서 내가 성취하고 싶은 것과 미래의 독자들에게 도움이된다고 생각합니다. 이것은 명령형 프로그래밍 모델보다 반응 형 프로그래밍 모델을 채택하는 방법을 제공합니다.

이벤트 소싱

여기서의 아이디어는 모든 응용 프로그램의 상태 전이를 불변 이벤트 형태로 나타내는 것입니다. 그런 다음 이벤트는 발생시 로그 또는 저널 형식으로 저장됩니다 ( '이벤트 저장소'라고도 함). 또한 시간이 지남에 따라 애플리케이션의 상태가 전체적으로 어떻게 진화했는지를 나타 내기 위해 무기한으로 쿼리 및 저장 될 수 있습니다.

이것이 달성하는 데 도움이되는 것은 마이크로 서비스가 중단되었지만 이와 관련된 다른 이벤트가 게시 되고 해당 마이크로 서비스의 다른 인스턴스가 이벤트를 소비하는 경우 해당 마이크로 서비스가 다시 시작되면이를 참조하여 event store모든 서비스를 검색 할 수 있다는 것입니다. 다운 된 기간 동안 놓친 이벤트.

이벤트 브로커로서의 Apache Kafka

초당 수천 개의 이벤트를 저장하고 발송할 수 있고 내장 된 복제 및 내결함성 메커니즘이있는 Apache Kafka의 사용을 고려하십시오. 그것은 디스크에 무기한으로 저장 될 수 있고 토픽 (카프카의 멋진 대기열)이 전달 될 때마다 (제거되지는 않지만) 소비 될 수있는 영구적 인 이벤트 저장소를 가지고 있습니다.

이벤트는 주제 내에서이를 식별 할 수있는 오프셋을 지정합니다. Kafka는 오프셋 자체를 관리하여 "최대 한 번"또는 "적어도 한 번"전달 의미를 쉽게 제공 할 수 있지만 이벤트 소비자가 토픽에 참여할 때 협상 할 수도 있습니다. 마이크로 서비스가 임의의 특정 시점 (일반적으로 소비자가 중단 한 장소)에서 이벤트 이용을 시작할 수 있습니다. 유스 케이스가 '성공적으로 완료'될 때 마지막으로 소비 된 이벤트 오프셋이 서비스의 로컬 스토리지에서 트랜잭션으로 지속되는 경우 해당 오프셋을 사용하여 "정확히 한 번"이벤트 전달 시맨틱을 달성 할 수 있습니다.

실제로 소비자가 Kafka에 자신을 식별하면 Kafka는 어떤 메시지가 어떤 소비자에게 전달되었는지 다시 기록하지 않도록 기록합니다.

사 가스

서로 다른 서비스 간의 통신이 실제로 필요한보다 복잡한 유스 케이스의 경우 유스 케이스 완료의 책임을 잘 인식해야합니다. 유스 케이스는 분산되어 있으며 관련된 모든 서비스가 해당 태스크를 성공적으로 완료 한 것으로 확인하면 완료됩니다. 그렇지 않으면 전체 유스 케이스가 실패해야합니다 잘못된 로컬 상태를 롤백하려면 수정 조치를 트리거해야합니다.

이것은 사가가 시작될 때입니다. saga는 일련의 로컬 트랜잭션입니다. 각 로컬 트랜잭션은 데이터베이스를 업데이트하고 메시지 또는 이벤트를 게시하여 saga에서 다음 로컬 트랜잭션을 트리거합니다. 로컬 트랜잭션이 비즈니스 규칙을 위반하여 로컬 트랜잭션이 실패하면 saga는 이전 로컬 트랜잭션에서 작성된 변경 사항을 취소하는 일련의 보상 트랜잭션을 실행합니다. 더 많은 정보를 원하시면 이것을 읽으십시오 .


나는 왜 당신이 그렇게 복잡한 구조를 만들고 싶어하는지 이해하지 못합니다. 일반적으로 각 서비스가 자체 데이터를 보유하고 요청시 다른 서비스에 제공하는 것이 훨씬 쉽습니다.
J. 파비안 마이어

^ 그러나 시스템의 가용성이 감소합니다. 높은 복원력이 필요한 경우 복잡한 구조가 보장 될 수 있습니다.
avmohan 2019

1

늦어도 이벤트 중심의 마이크로 서비스 아키텍처를 평가할 때 중요한 시점이라고 생각하기 때문에 2 센트를 논쟁에 옮길 것입니다. 각 마이크로 서비스는 해당 상태에 영향을 미치는 이벤트가 무엇인지 정확히 알고이를 기다릴 수 있습니다. 마이크로 서비스를 사용할 수없는 경우, 실패한 마이크로 서비스에서 필요한 메시지를 "소비"할 수 없을 때까지 유지하는 구성 요소가 있어야합니다. 이것은 실제로 "제작자 / 소비자"모델이며 "게시 / 구독"모델이 아닙니다. 메시지 큐 (예 : Kafka, RabbitMQ, ActiveMQ 등)는 지속적인 큐 및 ack / nack 메커니즘을 제공하는 (이벤트 소싱과 같은 다른 것을 구현하지 않는 한) 일반적으로이 동작을 달성하는 가장 좋은 방법입니다.

이제 마이크로 서비스는 메시지가 결국 전달된다는 것을 알고 있지만 충분하지 않습니다. 단일 메시지의 전달을 예상하는 방법은 무엇입니까? 동일한 이벤트 알림의 여러 사본 전달을 관리 할 수 ​​있습니까? 이것은 의미 론적 전달의 문제입니다 (적어도 한 번, 정확히 한 번)

마지막 생각들):

  1. 다른 사람의 이벤트를 소비해야하는 마이크로 서비스를 아키텍처에 추가 할 때는 첫 번째 동기화를 수행해야합니다

  2. 브로커도 실패 할 수 있으며이 경우 메시지가 손실됩니다

두 시나리오 모두 마이크로 서비스 상태를 재수 화하는 간단한 메커니즘을 갖는 것이 유용합니다. REST API 또는 메시지를 보내는 스크립트 일 수 있지만 가장 중요한 것은 일부 유지 관리 작업을 수행하는 것입니다.


0

당신은 게시자 / 가입자 모델을 사용하여 일반 이벤트 큐를 대체 할 수있는 A서비스가 화제의 새 메시지 게시 T를 하고 B동일한 주제에 가입 할 microservices의 입력합니다.

이상적으로 B는 상태 비 저장 서비스가되며 분리 된 지속성 서비스를 사용하여 실패한 B서비스 인스턴스가 하나 이상의 B서비스 인스턴스를 생성 하여 동일한 공유 지속성 서비스를 읽고 작업을 계속 하도록 대체 합니다.


0

A가 어떤 메시지가 변경되었다는 메시지를 게시하면 B는 해당 메시지를 사용하고 A 정보의 로컬 사본을 복제하여 B가 필요한 모든 작업을 수행 할 수 있습니다.

B가 A의 내부 데이터에 액세스 할 수있게하려면 A의 내부 데이터베이스에 대한 액세스 권한을 부여하는 것이 좋습니다.

그러나 그렇게하지 말아야합니다. 서비스 지향 아키텍처의 요점은 서비스 B가 서비스 A의 내부 상태를 볼 수 없으며 REST API를 통해 요청하는 것 (및 그 반대)으로 제한된다는 것입니다.

귀하의 경우 모든 사용자 데이터를 저장해야하는 사용자 데이터 서비스가있을 수 있습니다. 해당 데이터를 사용하려는 다른 서비스는 필요할 때만 데이터를 요청하고 로컬 사본을 보관하지 않습니다 (btw.는 GDPR 준수에 대해 생각할 때 실제로 유용합니다). User Data 서비스는 "새 사용자 만들기"또는 "user_id 23의 이름 변경"과 같은 간단한 CRUD 작업을 지원하거나 더 복잡한 작업을 수행 할 수 있습니다. "다음 2 주 안에 생일이있는 모든 표준 사용자를 찾아서 제공합니다. 프리미엄 평가판 상태 "를 참조하십시오. 이제 결제 서비스에서 사용자 42에게 이메일을 보내야 할 경우 사용자 데이터 서비스에 "user_id 42의 이메일 주소는 무엇입니까?"라고 묻고 내부 데이터를 모든 결제 정보와 함께 사용하여 이메일을 작성하고 전달할 수 있습니다. 전자 메일 주소와 본문을 메일 서버로 보냅니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.