spring websocket 을 공부하다보니, 기존에 알고 있던 redis pub/sub 에서의 channel 개념과 kafka 의 토픽 개념들이 헷갈리기 시작했다.
redis pub/sub 에서 말하는 channel 의 정체는 무엇일까?
connection
일반적인 웹 애플리케이션 서버들과 클라이언트와의 관계는 http 통신을 통해 비연결적이다.
하지만 db, redis 와 같은 서버들과 이를 연결하는 웹 애플리케이션 서버는 tcp 를 통해 연결되어 있다.
즉, 일단 접속을 하면 tcp 를 통해 연결이 되어있다.
redis pub/sub
pub/sub
일반적으로 pub/sub 은 broker 를 매개로 하여, publisher 가 메시지를 발행하고, subscriber 가 메시지를 수신하는 통신 방법을 말한다.
pub/sub 모델에서는 아래와 같은 구성요소를 일반적으로 포함한다.
- publisher: 메시지를 전송하는 애플리케이션
- subscriber: 메시지를 수신하는 애플리케이션
- topic : 메시지를 구분하기 위한 일종의 구분자. 파일, 메모리로 구현된다.
- message : publisher 와 subscriber 각 시스템이 각각 송신, 수신하고자하는 데이터를 말한다.
- broker : publisher 와 subscriber 사이에 미들웨어로써 동작하며, 메시지를 라우팅해주는 역할을 한다.
relay 로 동작함
kafka 의 경우, 발행된 이벤트들을 저장하기 때문에 이벤트를 비동기적으로 가져가서(pull) 처리할 수 있다.
하지만 redis pub/sub 은 redis 가 현재 연결된 subscriber 들에게 broadcasting 하고 메시지를 저장하지 않는다. 즉, subscriber 가 연결 상태에 따라 메시지를 수신하지 못할 수 있다.
따라서, 메시지가 유실되면 안되는 상황에서는 redis pub/sub 을 사용해서는 안된다.
그리고 redis pub/sub 에서 publisher 입장에서 fire & forgot 방식으로 동작한다.
kafka 의 경우 설정에 따라서, ack 를 받아야만 하도록 동작할 수 있지만 redis pub/sub 은 위의 특징으로 인해 subscriber 의 메시지 수신 여부를 체크하지 않는다.
redis pub/sub 메커니즘
redis 내부적으로 pubsub channel 을 map<채널 이름, Set<Client>> 형태로 보관하고 있다.
이 client 객체는 socket 으로 실제 tcp 로 연결된 객체들을 추적한다.
만약 실제 client 가 SUBSCRIBE 요청을 하면, channel map 의 집합에, client 객체를 추가한다.
UNSUBSCRIBE 요청시, client 객체가 가진 subscribe 중인 channel 정보를 이용해서 연결을 끊어준다.
메모리 구조
pubsub channels 는 논리적으로 map 구조를 가지고 있지만 내부 구현에는 hash table 을 사용하고 있다.
채널이름의 해싱 값을 인덱스로 배열의 인덱스를 찾고 해당 배열에 연결된 client 들을 찾는다.
pub/sub 퍼포먼스
pub/sub 자체의 해시 테이블은 점진적으로 조정하기 때문에 성능적으로 크게 문제가 되지 않는다.
하지만 client 가 UNSUBSCRIBE 요청을 하는 경우, 해당 클라이언트가 구독하고 있는 모든 채널을 순회하며,
버킷에 저장된 clients 객체들을 제거해야한다. 이는 구독한 채널별로 O(n) 복잡도를 가지고 있는 명령어라고 볼 수 있다.
서버가 자주 배포되고, 많은 파드가 배포되는 환경에서 pub/sub 을 사용하는 것은 redis 의 처리량에 안좋은 영향이 있을 수 있다.
'데이터베이스' 카테고리의 다른 글
MySQL(InnoDB)이 잠금할 레코드를 고르는 방법 (1) | 2024.06.05 |
---|---|
redis lock 1부 (feat. Redlock) (0) | 2024.05.03 |
왜 많은 회사들은 READ COMMITTED를 사용할까? (0) | 2023.07.07 |