Polling을 하면 consumer 입장에서 원하는 만큼만 가져올 수 있기에 이를 통해 부하를 조절할 수 있다. Kafka, AWS SQS 등과 같은 distributed queueing system에서 이러한 식으로 컨트롤한다.
Pushing을 하면 consumer 입장에서는 이벤트를 바로 알 수 있다. 즉각적인 액션이 취해져야 하는 경우 유용하다. AWS SNS(Simple Notification Service) 등이 이에 포함될 수 있다.
Consumer read pattern
Load balancing: 여러 소비자가 하나의 토픽을 소비하는 작업을 공유
Fan out: 각 메세지를 복수 개의 소비자로 전달
Kafka에서는 일반적으로 Load balancing과 Fan out을 같이 사용한다고 볼 수 있을 것 같다. 같은 소비자 그룹 내에서는 Load balancing을 하지만, 서로 다른 소비자 그룹에서는 Fan out.
다만, AWS SQS를 사용할 때는 SNS를 같이 사용해야 한다. 기본적으로 SQS가 단일 소비자 모델이기 때문에.
Log-based message broker: 생산자가 보낸 메시지는 로그 끝에 추가하고 소비자는 로그를 순차적으로 읽어 메시지를 받는다.
각 파티션은 다른 파티션과 독립적으로 읽고 쓰기가 가능한 분리된 로그가 된다.
각각 파티션에서 Offset을 통해 순차적으로 읽음.
로그 기반 접근법은 당연히 팬 아웃 메시징 방식을 제공. 독립적으로 읽을 수 있고, 삭제되지 않음.
만약 장애가 발생한 소비자가 처리했지만, 아직 오프셋을 기록하지 못한 메시지가 있다면 이 메시지는 재시작할 때 두 번 처리된다. 멱등성을 보장한다면 두 번 처리하게 되더라도 문제 없다.
여러 시스템 동기화 유지하기: 데이터베이스에 아이템 하나를 갱신하면, 캐시/색인/데이터 웨어하우스도 마찬가지로 갱신해야 하는 경우
일괄처리 방식으로 데이터 웨어하스로 벌크 로드
Dual write: 데이터베이스의 아이템을 갱신할 때, 다른 시스템에도 update
문제 1) 경쟁 조건. X=A와 X=B의 요청을 처리하는 도중, 데이터베이스에는 A → B로 적용되었지만, 검색 색인에는 B → A로 적용될 수도 있다.
이런 경우 Lock을 거는 것이 일반적일 것 같음. 버전 벡터와 같은 동시성 감지 매커니즘을 사용할 수도 있을 듯.
문제 2) 한쪽 쓰기가 성공할 때 다른 쪽 쓰기는 실패할 수 있는 점.
원자적 커밋 문제로 동시 성공 또는 동시 실패를 하도록 하면 된다.
CDC(Change Data Capture): 변경 데이터 캡처
변경 데이터 캡처는 메시지 브로커와 동일하게 비동기 방식으로 동작한다.
복제 지연으로 인한 단점이 존재 - 데이터베이스에서의 불일치 발생 가능. 최종적 일관성은 지킬 수 있음.
최근 변경 사항만으로는 충분하지 않기에 Snapshot 반영이 필요한데, Log compaction을 이용하면 매번 snapshot을 만들 필요가 없다. 주기적으로 같은 키의 로그 레코드를 찾아 중복을 제거하고 각 키에 대해 최신 내용만 유지한다. Compaction과 병합 과정은 백그라운드에서 진행됨.
Apache Kafka도 로그 컴팩션 기능을 제공하고, 새 소비자는 컴팩션된 로그 토픽의 오프셋 0부터 시작해서 순차적으로 데이터베이스의 모든 키를 스캔하면 된다.
Event sourcing: CDC와 같이 저수준에서 상태 변경을 하는 것이 아니라 Application 수준에서 발생한 일을 반영하게끔 설계되었음.
좀 더 비즈니스 로직 관점에서 컨트롤 할 수 있고, 이슈가 발생했었을 때 영향 범위도 직관적이지 않나
Event sourcing의 철학은 Event와 Command를 구분하는데 주의한다. 사용자 요청이 처음 도착했을 때는 Command, Validation을 통과한 후에는 Event.
“로그가 진실이고 데이터베이스는 로그의 부분 집합의 캐시다”
불변 이벤트의 장점
“실수가 발생해도 회계사는 원장의 잘못된 거래 내역을 지우거나 고치지지 않는다. 대신 실수를 보완하는 거래 내역을 추가한다”
“추가만 하는 불변 이벤트 로그를 썼다면 문제 상황의 진단과 복구가 훨씬 쉽다”
CQRS(Command Query Resposibility Segregation): 읽기 모델과 쓰기 모델을 다르게 가져가는 방식.
CQRS 패턴을 사용할 때, NoSQL에는 역정규화된 데이터를 저장하여 읽기 효율성을 높이려고 하는 경우도 있는 것 같음.
이런 경우 읽기 뷰에 반영되지 않을 가능성도 있기에 이를 위해 읽기 뷰를 동기식 업데이트 하는 등으로 해결을 할 수도 있다.
1) Batch Service vs Stream Service
2) Glossaries
3) 메시징 시스템의 종류
3-1) 생산자에서 소비자로 메시지 직접 전달
3-2) Message Borker
JMS(Java Message Service)
orAMQP(Advanced Message Queueing Protocol)
특징
3-3) Log-based Message Broker
특징
Partitioning
을 통해처리량(Throughput)
확보Replication
을 통해가용성(Availability)
확보끄적끄적
메시지를 재처리하기 위해 다른 위치에 출력을 기록할 수 있다