본문 바로가기

학습 기록 (Learning Logs)/Today I Learned

마이크로서비스 데이터 일관성

마이크로서비스 데이터 일관성

 

마이크로서비스 혹은 분산 시스템에서 데이터 일관성을 유지하기 위한 전략을 고민하거나 적용한 경험이 있다면 공유해주세요. 규모가 작아도 서비스 간 데이터 처리 흐름을 설계해본 경험이면 충분합니다.

 

단일 DB 트랜잭션이 아닌, 서비스 간 데이터 일관성을 유지하는 방식을 고민해본 경험을 떠올려 보세요. (예: Eventual Consistency, 이벤트 기반 처리, SAGA 패턴 등)

 

MSA에서는 하나의 application에서 서로 다른 table을 transaction을 사용할 수 없기때문에, 이벤트 방식으로 관리하여, transaction처럼 성공 후, 실패 후 이벤트를 발행하여, 데이터의 일관성을 유지/처리 해야 합니다.

제가 설계하고 개발한 것 중에서 MSA에서 데이터 일관성은 재고문제를 예시로 들겠습니다. 아이폰이 100대이면 순서대로 재고를 감소시켜야했습니다.


1. 서버 한 개 + 요청은 여러 개
각 서버가 한대씩 있다는 전제 하에서도 request는 동시에 요청이 올 수 있습니다. 
이런 경우 마지막 재고 5개 중에서 첫 번째 사람은 3개 두번째사람은 1대 마지막 하나를 두고 동시에 1개씩 요청을 했다고하면, 좀 더 빨리 요청을 보낸 쪽이 성공, 좀 더 늦게 요청한 사람은 실패로 이벤트를 처리해야합니다. transaction처럼 atomic 주문, 결제, 재고 감소가 하나의 로직으로 작동하도록, 재고부족으로 주문 실패한 request은, 주문을 실패로 상태를 변경하고, 결제를 환불하는 이벤트를 발행 해야 합니다.

이벤트 관리는 queue 자료구조를 사용하여 데이터를 순서대로 처리할 수 있습니다.  rabbitMQ를 사용하거나 kafka로 재고 수량을 감소하는 이벤트를 발생시킵니다. 

저는 rabbitMQ도 해보고, Kafka도 사용해봤으나 마지막에는 kafka로 이벤트 처리로 수량을 감소시키고, 성공하면 주문완료 상태로 변경시키고, 주문이 실패면 환불을 요청하는 이벤트로 전환하는 것을 설계하고 구현했습니다. 

kafka에서 토픽에 파티션을 하나로 두어서 순서대로 요청이 들어온 순서대로 처리를 했습니다. 
따라서 토픽당 파티션은 하나로 설정해야합니다. 하지만 파티션이 하나면, 컨슈머 그룹을 설정하더라도 하나만 컨슘이 발생합니다.

2. 서버 여러대
서비스별로 서버가 여러대 환경에서는, 이벤트를 병렬로 빠르게 처리하기위해서는, 서버별로 컨슈머그룹아이디를 다르게 해서 처리할 수 있습니다. 그러면 파티션이 하나여도 순서대로 데이터를 빠르게 소비할 수 있습니다.

SAGA패턴은 외국에서 쓰이는 단어로는 서사라고 불립니다. 위에서 제가 설명했던 것처럼, 주문,결제완료 후 재고 감소를 요청했는데 실패한 경우 결제를 환불로 변경하고, 주문 완료에서 주문 취소로 상태를 변경하는 하나의 서사, 이야기가 완성됩니다.

MSA에서는 서버가 서로 분리되어있기때문에 어떤 순서대로 각각의 서비스가 이야기를 소비할지를 순서를 지켜야합니다.
이를 중앙에서 관리하는 오케스트라 방법이 있습니다. 이는 지휘자가 이벤트를 한곳에서 흐름을 관리하기때문에 전체흐름을 한곳에서 정리하지만, 한곳에 몰려있기때문에 관리하기 어려우면서도 복잡해집니다.
반면 저는 각 서버의 흐름을 알고있다는 전제로 이벤트를 발생시키는 코레오그래피 방법을 사용했습니다.