이전 버전에서 새롭게 수정된 부분과 최종적으로 완성된 아키텍처를 기록한다. (개발하면서 개선해 갈 예정)
개발하면서 변경될 수도 있지만 일단 현재 결정된 아키텍처📍
메시지 브로커로서 redis를 사용할 때 대용량 데이터 처리에서 문제가 발생하진 않을까?
redis cluster 구축해보자
레디스 클러스터 보다는 일정시간마다 데이터베이스에 데이터를 저장하는 편이 더 낫지 않을까?
2-1. 그러면 nosql로 바로 접근하는게 낫지 않을까?
이 부분은 구글링을 하면서 정확히 어떤 부분을 고민했던것인지 더 정확해졌다. 정확하게 우려했던 부분은 "레디스를 메인 스토리지로 이용할 때 메모리 용량이 부족하지 않을까?"였다. 관련 내용을 찾아봤고 찾아본 결과 "서비스가 성장하고 저장해야 하는 데이터양이 증가하면서 문제가 될 수 있다"로 결론을 내렸다.
참고한 링크
https://charsyam.wordpress.com/2012/04/29/%EB%B0%9C-%EB%B2%88%EC%97%AD-line-%EC%8A%A4%ED%86%A0%EB%A6%AC%EC%A7%80-%ED%95%9C%EB%8B%AC%EC%97%90-%EC%88%98%EC%8B%AD%EC%96%B5-%EA%B1%B4%EC%9D%98-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A5%BC-redis%EC%99%80/
https://engineering.linecorp.com/ko/blog/LINE-integrated-notification-center-from-redis-to-mongodb
그래서 mongodb에 데이터를 저장하는것으로 결정했다.
1.유연한 스키마(추후 데이터 추가 및 변경 될 수 있음)
2.수평적 확장이 쉽다
3.데이터 접근 지연시간이 낮음
4.TTL 인덱스 지원
채팅 데이터는 라이브 방송이 끝나면 삭제되어야한다.
5.read/write 성능 뛰어남(write에 최적화된 cassandra 제외)
6.러닝커프가 너무 높지 않은 수준이어야함(hbase 제외)
이후 성능 테스를 통해 캐시를 도입해서 응답 속도를 높이는 것도 좋을 듯하다.
질문
저희 팀 프로젝트에서는 채팅에서 사용자들끼리 서로를 신고할 수 있고 신고횟수가 일정 수 이상 되면 해당 사용자의 채팅을 막고있습니다. 이때 신고 서버에서는 http api를 통해 사용자 신고를 받고 있고 요청을 받아서 이 데이터를 캐시 서버에 저장하면 채팅 서버에서 이 캐시 데이터를 확인해서 사용자의 채팅을 차단하는식으로 설계해두었는데 msa관점에서 이 두 서버가 동일한 캐시를 공유해도 되는것인지? 공유할 수밖에 없다면 굳이 두 서버를 분리할 필요가 없는게 아닌지? 의문이 들었습니다. 두 서버를 분리하는게 맞을까요?
요약하자면,
피드백 주신 내용을 바탕으로 신고를 분리할 필요가 있나 생각해 봤다.
결론적으로 먼저 "분리하는 것으로 결정" 하였는데 이유는
1. 우리 팀 프로젝트의 목표는 '대용량 시스템 설계 능력 함양"이다.
채팅 서버는 많은 트래픽이 발생하는 부분이기 때문에 오롯이 채팅 기능만 담당하는 게 좋을 것 같다고 생각했다.
2. 신고 도메인은 방송자가 시청자를 신고 및 강퇴하는 경우 등등 추후 다른 요구사항이 추가될 수 있다.
변경된 부분은 채팅 메시지 저장 부분이다. 기존에는 레디스를 메인 스토리지로 이용했던 부분이 nosql에 저장하는 것으로 바뀌었다.
그리고 채팅 서버들 사이에 차단 사용자 캐시를 공유한다.
차단 사용자 캐시는 신고 서버에서 kafka에 이벤트를 발행하면
캐시 서버들 중 하나가 이벤트를 받아 차단 캐시를 업데이트하고 클라이언트로 차단된 사용자 정보를 전송한다.(웹소켓 통해)
그러면 각 채팅 서버로 채팅 메시지 전송 요청이 들어오면 채팅 서버는 차단 사용자 캐시를 확인하고 채팅이 차단된 사용자라면 채팅 메시지를 보내지 않는다.
이때 차단된 사용자의 경우 이 사용자가 이전에 보낸 채팅 메시지들을 "차단된 사용자입니다" 이런 식으로 가려야 하는데 이 사용자가 이전에 엄청나게 많은 채팅 메시지를 전송했다면 많은 업데이트 연산이 발생할 수 있기 때문에 별도의 배치 서버에서 처리하는 것으로 결정했다.
채팅방 정보를 저장할 필요가 있는데 DB에 저장이 필요하지 않고 방송이 끝나면 휘발되는 데이터는 레디스에 저장하는 것으로 결정했다.
신고 서버와 채팅 서버를 분리하는 것으로 결정했기 때문에 신고 서버에서는
신고 요청이 들어왔을 때 mysql에 데이터를 저장하고 로컬 캐시를 통해 "어떤 사용자가 몇 번 신고되었는지"를 저장한다.
그리고 만약 신고 횟수가 10번이 되면 kafka에 이벤트를 발행한다.
데이터베이스는 안정성을 보장하며 오픈소스이고 레퍼런스가 많은 mysql로 결정했다.
2023.01.18 추가 🔽
참고 자료
스마일게이트 강의
https://rapidapi.com/guides/difference-kafka-rest
https://www.interviewbit.com/blog/rabbitmq-vs-kafka/
https://velog.io/@cho876/카프카kafka-vs-RabbitMQ
2023.01.27 추가 🔽
미디어 서버에서 채팅 서버로 rest-api 호출을 할 때 적어도 한번 전달되도록 보장할 수 있는지를 생각해 보게 되었음
추가로 미디어 서버에서 채팅방 서버로 제때 api 호출을 하지 못해 메시지 전송 요청이 왔을 때 미디어 서버로 api 호출을 해서 채팅방 생성 여부를 확인하게 되는데 이때 시간이 오래 걸리지 않을까?
-> 첫 사용자의 메시지 전송 요청에만 약간 시간이 걸리고 이후부터는 정상적으로 요청을 처리하기 때문에 괜찮을듯.
참고자료: https://youtu.be/uk5fRLUsBfk