
관계형 데이터 베이스 기반의 MSA에서 kafka, elasticsearch, redis가 어떤 역할을 할까?
각 구성 요소에 대한 이해는 MSA에서 데이터를 어떻게 효율적으로 전달하고 처리하며 저장하는지를 이해하는데 핵심요소이다.
하나의 큰 시스템을 여러 개의 독립적인 작은 서비스 단위로 나누어 개발, 배포, 운영하는 아키텍처 스타일이다.
이때 서비스 간 통신은 REST API, 메시지 브로커(Kafka)등을 통해 이루어진다.
서비스 간 DB를 공유하지 않고 독립적인 DB를 사용하는 것이 원칙이다.
각 MSA는 다제 데이터베이스를 가지고 있으며, RDB를 사용하는 경우가 많다
그러나 RDB많으로는 로그 수집, 메시지 큐, 캐싱 등 다양한 기능을 효율적으로 처리하기 어렵다
따라서 Kafka, Elasticsearch, Redis같은 비관계형 도구들이 보완적으로 사용되는 것

대용량의 데이터를 비동기적으로 전달하는 분산 메시지 스트리밍 플랫폼이다.
MSA간의 비동기 통신을 가능하게 만들어준다
서비스 간의 강한 결합을 피하면서 메시지의 유실 없이 저장이 가능하다.
핵심 고려사항은 다음과 같다.
Kafka는 기본적으로 메시지를 한번 이상(at least once) 보낸다.
이에 따라 DB에 같은 메시지를 두번 저장할 수 도 있다.
이 때 idempotent key(중복 방지 키)를 써서 이미 처리한 메시지인지 확인한다
또는 트랜잭션 기능으로 한 번만 저장하도록 묶는다.
Kafka에서 메시지를 읽을때 책갈피처럼 offset을 저장한다
오프셋을 commit 하느냐에 따라 메시지가 누락되거나 중복 처리 될 수 있다.
따라서 적절한 commmit & rollback 전략이 필요하다
메시지의 형식이 바뀌면 데이터를 읽는 쪽에서 해석할 수 없게 된다.
따라서 Schema Registry를 사용해서 데이터 형식을 등록하고 버전을 관리한다.
Consumer(받는 쪽)가 너무 느리면 Kafka에 메시지가 쌓인다
이럴 때는 batch로 묶어서 처리하거나, 느린 속도에 맞춰서 조절한다.
Kafka는 Partition을 기준으로 메시지를 나눈다.
같은 키(ex: user_id)를 묶으면 순서가 유지된다
오류난 메시지는 메시지를 다시 보내거나 DLA(Dead Letter Queue)에 따로 저장해서 나중에 처리한다.

분산 검색 엔진으로, 대용량 데이터를 실시간으로 검색, 분석할 수 있다.
JSON 기반으로 문서를 저장하며, NoSQL의 일종이다.
RDB보다 검색 성능이 뛰어나서 사용하는 것으로 복잡한 텍스트를 검색하고 필터링하는데 뛰어나다.
뿐만 아니라 실시간 로그 분석 및 에러 추적에 효과적이다.
핵심 고려사항은 다음과 같다.
DB와 ES의 데이터는 동기화 되어야 한다
DB의 데이터가 바뀌면 ES에서도 반영되어야 한다.
Kafka,Logstash,CDC 도구를 써서 자동으로 동기화시킨다
index는 검색을 위한 디렉토리이다.
따라서 어떤 구조로 데이터를 쌓을지 어떻게 계획하냐에 따라 검색 속도가 달라진다.
ES는 DB처럼 데이터가 완전히 최신 상태이지 않을 수 있다.
이를 eventual consistency라고 한다
하나하나 넣는것보다 여러개를 묶어서 처리해야 빠르다
문서에 고유 ID를 넣어주지 않으면 중복 저장이 된다.
검색어를 잘게 쪼개면(ngram) 검색어 가중치 조절 등으로 성능을 높일 수 있다
하지만 너무 많은 와일드카드는 느려진다는 위험성이 있다.

인메모리 기반의 Key-Value 캐시 저장소이다.
데이터를 디스크가 아닌 RAM에 저장하므로 속도가 매우 빠르다
DB나 외부 API 요청 결과를 캐싱하여 속도를 높인다
이를 통해 DB의 부하가 감소된다.
핵심 고려사항은 다음과 같다.
캐시는 오래된 데이터를 가지고 있을 수 있다
이때 DB와 캐시를 어떻게 동기화할지 전략이 필요하다
(Write-through, write-behind, cache aside)
Time To Live를 정해서 자동으로 캐시를 삭제하게 한다
그렇지 않다면 캐시에 오래된 데이터가 남게 된다.
데이터를 구분하기 쉬운 명확한 key를 쓰고, TTL도 잘 지정해야 한다
Redis는 임시 저장소이다. 따라서 항상 DB와 같이 쓰는게 원칙이다.
Redis는 메모리 기반이라 꽉 차면 데이터를 버리는 정책이 필요하다
(LRU, LFU)
Redis가 장애가 발생한다면 Sentinel이나 Cluster 모드를 통해
Redis를 여러 개로 구성해서 고장에도 대비한다.