데이터 복제가없는 마이크로 서비스


19

가장 단순한 마이크로 서비스 디자인을위한 데이터 복제 또는 공유 데이터베이스를 피하는 것이 어렵다는 것을 알게되었습니다. 다음은 제가 직면 한 문제의 기본 예입니다. 누군가 웹 응용 프로그램을 사용하여 인벤토리를 관리한다고 가정하면 두 가지 서비스가 필요합니다. 하나는 품목을 관리하는 재고 및 재고 수량과 사용자 데이터를 관리하는 사용자 서비스를위한 것입니다. 데이터베이스를 비축 한 사람에 대한 감사를 원할 경우 재고 서비스의 데이터베이스에 사용자 ID를 마지막 재고 값으로 추가 할 수 있습니다.

응용 프로그램을 사용하여 우리는 부족한 모든 항목과 마지막으로 물건을 비축 한 사람의 목록을보고 다시 재고를 요청할 수 있습니다. 위에서 설명한 아키텍처를 사용하면 수량이 5 미만인 모든 품목의 품목 세부 사항을 검색하도록 재고 서비스에 요청합니다. 그러면 사용자 ID를 포함한 목록이 리턴됩니다. 그런 다음 인벤토리 서비스에서 얻은 사용자 ID 목록에 대한 사용자 이름 및 연락처 세부 정보를 얻기 위해 사용자 서비스에 대한 별도의 요청이 이루어집니다.

이것은 매우 비효율적이며 다른 서비스 API에 여러 번 요청하기 전에 여러 데이터베이스 쿼리를 작성하기 전에 더 많은 서비스가 필요하지 않습니다. 대안은 인벤토리 데이터에서 사용자 세부 정보를 복제하는 것입니다. 사용자가 연락처 세부 정보를 변경하면 다른 모든 서비스를 통해 변경 사항을 복제해야합니다. 그러나 이것은 마이크로 서비스의 제한된 컨텍스트 아이디어와 맞지 않는 것 같습니다. 또한 단일 데이터베이스를 사용하고 다른 서비스간에이를 공유 할 수 있으며 통합 데이터베이스의 모든 문제를 해결할 수 있습니다 .

이것을 구현하는 올바른 방법은 무엇입니까?


5
마이크로 서비스의 역설에 오신 것을 환영합니다. 일을 더 단순하게 만드는 것은 실제로 일을 더 복잡하게 만들 수 있습니다.
Robert Harvey

"올바른"방법은 항상 그렇습니다. 특정 목표에 가장 적합한 것을 수행하는 방법을 찾으십시오.
Robert Harvey

1
@RobertHarvey 항상 그렇지만 교과서 마이크로 서비스 방식을 이해하려고 노력하고 있습니다. 이상적인 세상에서 어떻게 작동해야하는지 이해하면 사용 사례에 맞게 행복하게 변경하겠습니다.
Geraint Anderson

1
그러나 효율성 측면에서 문제의 프레이밍은 작동하지 않는 소프트웨어 요구 사항입니다. 효율성 문제를 해결하는 방법은 데이터베이스에 직접 문의하는 것입니다.
Robert Harvey

1
나는 당신과 똑같은 질문을하려고했지만, 여전히 단순한 웹 애플리케이션에 대한 MSA의 장점은 아직 보지 못했습니다. 많은 경우 모듈화가 복잡하지 않으면 서 달성 될 수 있다고 생각합니다.
Glasnhost

답변:


10

복제해야 할 부분이 완전히 없습니다.

마이크로 서비스의 중심 원칙은 서비스가 단일 권한이되는 것입니다. 즉, 재고와 사용자 관리가 완전히 분리 될 수 있습니다. 재고 시스템이 존재한다는 것을 알지 못하도록 사용자 관리를 설계했습니다.

그러나 인벤토리 시스템은 사용자 ID 이외의 사용자에 대해서는 아무것도 저장하지 않도록 설계했습니다. 사용자 정보 변경 전파 문제를 처리합니다.

로그, 감사 및 인쇄물과 같은 인벤토리 정보와 사용자 정보가 모두 필요한 정보는 정보가 변경 될 때 업데이트되지 않습니다. 그들은 무엇이 었는지에 대한 기록입니다. 다시, 당신은 변화를 전파하지 않습니다.

따라서 모든 경우에 최신 사용자 정보를 원할 때 사용자 정보 서비스를 요청하십시오.


@Geraint : 시스템에서 어떤 종류의 복제가 발생하는지 더 구체적으로 설명 할 수 있습니까?
Robert Harvey

1
감사. 중복은 사용자 연락처 세부 사항을 인벤토리 서비스에 복사하는 것을 언급했지만이를 해결했습니다 (예 : 필요하지 않음). 인벤토리 데이터와 사용자 데이터를 얻을 수있는 단일 관계형 데이터베이스에서 첫 번째 결과가 반환 될 때까지 두 번째 API를 시작할 수없는 두 개의 고유 한 API 호출을 만드는 것은 직관적이지 않은 것 같습니다. 그러나 이것이 마이크로 서비스를 사용하는지 아니면 다른 것을 사용하는지에 대한 평가의 일부라고 생각합니다.
Geraint Anderson

DB를 모두 관리하는 경우 DB가 사용하는 것과 동일한 트릭입니다. 사용자 정보를 인벤토리 테이블에 복사하지 않습니다. 외래 키를 제공합니다. 사용자 ID가 여러 서비스에서 동일한 작업을 수행하고 있습니다. 독특하게 만드십시오.
candied_orange

It seems counter-intuitive to move from a single relational database where I could get the inventory data and the user data with a join"이상적으로"서비스 당 하나 이상의 상점이 있다는 것을 명심하십시오. 따라서 "경계"사이에 "결합"과 같은 것은 없습니다. 그 이유는 간단합니다. DB는 서비스간에 커플 링을 생성합니다. @CandiedOrange 제안과 달리 하나의 서비스에서 다른 서비스로 최소 데이터를 복제 할 수 있다고 생각합니다. 변경되지 않는 데이터를 참조하고 있습니다. 만약이 딥이 효율성과 성능을 향상시키고 (둘 다 필요하다면) "프로"는 아마도 "콘"을 상쇄 할 것입니다
Laiv

@GeraintAnderson 내 말은, 효율성이 필요하다면 (정의 적으로 비 기능적 요구 사항 인 경우) 그렇게 할 수있는 방법이 있습니다. 즉, 인벤토리 서비스에서 데이터 페이지 (예 : 10 개 요소)를 요청하고 각 페이지를 가져 와서 해당 페이지를 사용하여 사용자 서비스에서 데이터를 요청한 다음 마지막에 집계합니다. 이렇게하면 독립 서비스의 병렬 처리를 활용하면서 경계를 유지할 수 있습니다. 그럼에도 불구하고 해결해야하는 애플리케이션의 실제 병목 현상으로 식별 될 때까지 귀찮게하지 마십시오. 1 초 밤새 작업에서 1/2 초를 추가로 대기하는 것은 누구에게나 중요하지 않습니다.
Delioth

11

데이터 중복을 피하는 것이 어렵다는 것을 알고 있습니다 ....

마이크로 서비스 아키텍처에 관한 마이크로 소프트 전자 책에 따르면 , 데이터 복제에는 아무런 문제가 없다. 기본적으로 데이터를 복제하면 서비스 간의 분리가 증가하여 단일 권한으로서의 역할이 강화됩니다. 관련 구절 :

그리고 마지막으로 (마이크로 서비스를 구축 할 때 대부분의 문제가 발생합니다.) 초기 마이크로 서비스가 원래 다른 마이크로 서비스가 소유 한 데이터를 필요로하는 경우 해당 데이터에 대한 동기 요청에 의존하지 마십시오. 대신, 최종 일관성을 사용하여 (일반적으로 통합 이벤트를 사용하여) 해당 데이터 (필요한 속성 만)를 초기 서비스 데이터베이스에 복제 하거나 전파하십시오.


1
나는 완전히 동의하지 않습니다. 유지 관리가 더 어려워집니다. 무언가를 추가, 업데이트 또는 제거해야 할 때 마이크로 서비스 간의 트랜잭션을 구현할 수 있습니다. 단일 실패 지점을 방지하려는 경우 요청 또는 다른 유형의 캐싱을 사용할 수 있습니다.
Alan Sereb

1
@AlanSereb 유지하기가 어렵지만 요점은 때로는 다른 선택의 여지가 없다는 것입니다. 예를 들어, 두 데이터베이스에있는 개체간에 FK를 만들어야하는 경우 어떻게해야합니까? 로컬 DB에서 쿼리 할 때 일관성을 유지하는 유일한 방법은 데이터 복제를하는 것입니다. 다음을보십시오 : stackoverflow.com/a/4452586/2255491
David D.

나는 동의한다. 또 다른 좋은 방법은 이벤트 소싱 경로를 이용하는 것입니다. 이벤트 파이프 라인을 통해 모든 돌연변이를 실행
시키십시오

4

수량이 5 미만인 모든 품목의 품목 세부 사항을 검색하도록 재고 서비스에 요청합니다. 그러면 사용자 ID를 포함한 목록이 리턴됩니다. 그런 다음 인벤토리 서비스에서 얻은 사용자 ID 목록에 대한 사용자 이름 및 연락처 세부 정보를 얻기 위해 사용자 서비스에 대한 별도의 요청이 이루어집니다.

그렇습니다.

물론, 모놀리스에서는 관련 항목을 쿼리하고이를 사용자 모델에 공급하고 동일한 데이터를 얻는 인벤토리 모델을 가질 수 있습니다.

또는 동일한 관계형 데이터베이스에 저장하고 SQL을 작성하면 데이터베이스가 인벤토리 테이블과 사용자 테이블을 가져 와서 마술을 수행하고 원하는 데이터를 얻을 수 있습니다.

에 관계없이 당신이 그것을 할 방법의 어딘가에 됩니다 본질적으로, 재고 시스템에서 사용자 ID 목록을 가져 오는 사용자 시스템에 그들을 공급 및 데이터의 목록을 컴파일 코드합니다.

대답해야 할 질문은 성능 및 유지 관리 및 기타 "부드러운"특성에 관한 것입니다.

마이크로 서비스의 주요 이점은 확장입니다. 한 시스템에 1 만 명의 사용자가 있고 약간 느린 경우 다른 시스템을 추가 할 수 있으며 시스템이 두 배 빠릅니다. 8을 더 추가하면 10 배 빠릅니다. (선형 스케일링은 아마 낙관적이지만, 이상과 아닌 희망에 불합리한.)

그리고 이것은 서비스 당 입니다. 인벤토리 시스템에 병목 현상이 발생하면 사용자에 대한 보고서 이상의 용도로 사용되며 해당 서비스에만 더 많은 시스템을 추가 할 수 있습니다 . 기계는 또한 전문화 될 수 있습니다; 이 서비스에는 많은 메모리가 필요합니다.이 서비스는 많은 계산을 수행하고 더 많은 CPU가 필요합니다.

스케일링이 필요하지 않은 경우 마이크로 서비스의 또 다른 이점 은 모듈 식 입니다. 물론 모 놀리 식 응용 프로그램은 모듈 식 일 수도 있으며 표준화 된 데이터베이스가 있으며 실제로 모듈 사이의 벽은 유리 벽과 같고 모래의 선은 최악입니다. 마이크로 서비스는 단단한 강철로 분리됩니다.

사용자 시스템이 문자 그대로 화재를 발견하더라도 인벤토리 시스템에는 영향을 미치지 않습니다. 누가 무엇을 구입했는지에 대한 예쁜 보고서를 인쇄 할 수는 없지만 고객은 재고가있는 품목이 있다는 사실을 알고 안전하게 주문할 수 있습니다.

그리고 관계형 데이터베이스 (*)에서 수행하는 것 이상 으로 마이크로 서비스 에서 데이터를 복제하지 않습니다 . 관계형 데이터베이스에서는 join을 수행 할 수 있으며, 이와 같이 목록에 설명 된 것과 같이 목록을 병합하는 것과 같습니다.

뷰를 추가 할 수도 있습니다. 이에 상응하는 것은 병합을 수행하는 새 서비스를 추가하는 것입니다. 세 가지 요청이 발생합니다. 하나는 새 서비스에 해당하는 서비스는 원래 두 가지를 수행합니다. 관계형 데이터베이스에는 서비스 수준에서 구현해야하는 뷰를 최적화하는 멋진 기능이 있습니다. 당신은 "무료"를 얻지 못합니다.

캐싱은 두 값이 일치하지 않으면 어떤 값이 잘못되었는지를 알고 있다는 점에서 데이터 복제와 다릅니다. 일관성을 희생하여 가용성을 높이기 위해 마이크로 서비스에서 종종 사용됩니다 (CAP 정리). 관계형 데이터베이스는 일관성의 제단에서 가용성을 완전히 도살하기 때문에 일반적이지 않습니다. 캐싱을 용이하게하는 마이크로 서비스에는 고유 한 것이 없지만 실제로 캐싱은 주요 관심사이며 마이크로 서비스에서 캐싱을보다 쉽게 만듭니다 .

(*) 마이크로 서비스 떼에서 데이터를 복제하는 것이 합리적이라면, 동등한 관계형 데이터베이스에서도 의미가있을 것입니다.


3
"마이크로 서비스에서 데이터를 복제하지 마십시오"부분까지 귀하의 답변이 정말 마음에 들었습니다. 데이터 복제가 올바른 접근법 인 경우가 있다고 생각합니다. 내결함성과 자율성을 향상시킵니다. 사용자 서비스가 중단 된 경우 재고 서비스는 여전히 재고를 보유한 사람이 적은 재고 목록을 표시 할 수 있습니다.
피터 폼페이

1
@peterpompeii 데이터 중복이 아니라 캐싱이라고 부릅니다. 데이터 복제는 하나의 데이텀에 대해 업데이트 할 두 곳이 있고, 한 곳이있을 때 캐싱하고 다른 곳으로 자동 전파되는 경우입니다. 또한 나는 관계형보다 더 말했다. 관계형 데이터베이스에서 데이터를 복제하는 것이 합리적이라면 마이크로 서비스에서 의미가 있습니다. 나는 우리가 동의하고 그 부분이 더 명확 할 수 있다고 생각하지만, 지금은 전화 만 가지고 있으므로 지금 텍스트를 업데이트하지 않습니다.
Odalrick 2019

@PeterPompeii 캐싱에 대한 추가 섹션에서 문제가 해결되기를 바랍니다.
Odalrick

1
@Odalrick 당신이 묘사 한 것은 데이터 복제와 같습니다. 복제와 캐싱은 모두 데이터 복제 형식입니다. 복제는 항상 필요한 모든 데이터를 갖도록 사본이 보장되는 경우입니다. 캐싱은 주문형입니다. 캐싱은 놓칠 수 있습니다. 가용성 캐싱은 성능 캐싱만큼 의미가 없습니다. TL; DR 일관성이 충분한 전체 사본을 저장하는 경우 누락 여부를 확인할 필요가 없으며 캐시가 아닙니다.
Brandon

1
@Brandon 복제와 캐싱의 또 다른 차이점은 차이가있을 때 어떤 데이터가 잘못되었는지 아는 방법입니다. 복제는 데이터를 병합하는 방법에 대한 몇 가지 규칙을 정의합니다. 반면에 캐싱은 항상 : 캐시가 잘못되었습니다.
Odalrick
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.