Pub/Sub(발행-구독)형태는 현대 애플리케이션에서 비동기 이벤트를 처리하고 확장성을 확보하는 데 자주 사용되는 설계 방식이다.
하지만 이벤트 브로커는 메시지를 발행하고 구독자(Subscriber)가 가져가는 구조에서 몇 가지 중요한 점을 고려해야 한다.
Redis
Redis 의 pub/sub 은 스트림 형태로
publish 한 즉시 데이터가 subscriber 에게 전달되고 소멸되는 특성을 가지고 있다 (휘발성 데이터)
각 이벤트/메세지 브로커 마다 특성이 있으니 사용시 주의 하도록 하자
1. 메시지 중복
publisher 는 멱등성 프로듀서를 지원하는 이벤트 브로커도 있다
하지만 주는쪽 말고 받는 쪽에서도 중복처리에 대한 멱등성 처리를 신경써야 한다.
Unique key를 두어 데이터의 중복을 방지한다 ( 타임스탬프 , 트랜잭션ID )
2. 메세지 순서
데이터는 파티션에 저장이 된다. 하지만 여러 파티션에 저장되는 데이터를 가져올때는 순서가 보장되지 않는다.
2-1 단일 파티션
파티션을 지정해서 하나의 파티션에 데이터를 넣어준다.
(파티션 내에서는 순서를 보장한다.)
2-2 재정렬
데이터를 가져온 후 타임스탬프나 , 시퀀스 넘버를 기준으로 데이터를 재정렬 해준다.
2-3 파티션 키
데이터를 프로듀싱할때 지정하는 키를 같은 값으로 지정하는 것이다. (사용자ID , 주문ID)
위 같은 방법은 하나의 파티션 데이터가 몰릴 수 있다 하나의 파티션에는 하나의 컨슈머만 가져갈 수 있어서 파티션에 골고루 데이터가 분포되어 있지 않으면 다른 컨슈머는 노는 현상을 만날 수 있다 (데이터의 불균형)
3. 데이터 손실
네트워크 오류, 소비자 장애 등으로 인해 메시지가 손실 될 수 있다.
로컬 트랜잭션을 이용하여 데드레터큐에 넣고, 스캐쥴러로 실패한 메세지를 재처리 할 수 있도록 만들자
@Transactional
@Async
fun send(event: Event) {
val record = ProducerRecord(event.targetName.name,event.operation.name,event.body)
try {
kafkaTemplate.send(record)
}catch (e: Exception){
event.fail()
deadLetterRepository.save(event)
}
}
DeadLetter queue
https://soobysu.tistory.com/178
Transaction OutBox Pattern
https://soobysu.tistory.com/166
4. 메세지 발행 및 구독 속도 조절
메세지의 발행과 가져오는것의 속도를 조절해주지 않으면 시스템에서 장애가 발생한다.
1. 발행이 너무 빠르게 일어나서, 구독자가 데이터를 처리하는 속도를 못 따라가는 경우 ( OOM 발생 위험 )
2. 발행이 느리게 일어나서, 구독자가 대기하는 경우
두 경우 모두 성능을 제대로 사용하지 못하는 경우이다.
4-1 최적화 및 데이터 요약
- 소비자가 메시지를 처리하는 로직을 비동기로 처리 하거나 배치로 처리하여 성능을 최적화 한다
- 초당 1000건의 데이터가 들어온다면 데이터를 평균 및 요약하여 의미있는 데이터로 요약 한다
4-1 백프레셔
구독자가 데이터를 처리하는 속도에 비해 많은 양의 데이터를 받으면, 데이터가 쌓이면서 OOM 이 발생 할 수 있다.
이를 방지하기 위해 컨슈머에서 데이터를 가져오는 속도를 조절해 주는 장치가 필요하다.
이렇게 하면 해결점은 아니다. 백프레셔를 통해 안정적인 데이터 소비를 하더라도
메세지큐에서는 데이터가 엄청나게 쌓이고 있기 때문에 그에 맞춰 컨슈머의 수평확장이나 추가적인 조치가 필요하다.
5. 운영 모니터링 및 로그 관리
데이터 처리에만 급급하면 안된다.
여러 브로커를 관리하려면 상태와 성능을 모니터링 하고 테스트 하면서 안정적인 서비스를 구축 해 나아가야 한다
(Kafka Manager, Prometheus)
'개-발 > Infra' 카테고리의 다른 글
[Infra] 데이터의 멱등성 (0) | 2024.12.13 |
---|---|
[nGrinder] 내 서버는 어느정도 까지 버틸까 (stress Test) (0) | 2024.11.21 |
[nGrinder] multipart-form 스크립트 작성하기 (1) | 2024.11.19 |
[Infra] ngrinder 부하 테스트 도구 (1) | 2024.11.18 |
[Infra] Jmeter 부하 테스트 도구 (1) | 2024.11.18 |