전체 글 (10) 썸네일형 리스트형 SNS 서비스 | 10. 좋아요 병합 스케줄러 앞서 좋아요 요청의 잠금 경합으로 인한 병목 지점을 개선하고자 레디스에 좋아요 데이터를 캐싱하는 방법을 사용하였습니다. 이 무한히 늘어날 수 있는 문제가 있는 좋아요 데이터는 일정 주기로 데이터베이스에 병합되야 합니다. 병합은 다음과 같은 순서로 이루어집니다. 1. 락 획득2. 좋아요 키 조회3. 좋아요 데이터베이스 저장4. 좋아요 키 삭제5. 락 해제 분산 락 기법을 통한 분산 서버 환경에서의 동시성 제어는 앞서 피드 삭제 스케줄러를 구현할 때 해결할 수 있었습니다.좋아요 키 조회좋아요 데이터를 저장하는 키는 post:*:like 키 패턴으로 조회가 가능합니다. KEYS 커맨드와 SCAN 커맨드의 차이를 알아보겠습니다. KEYS 커맨드는 주어진 패턴과 일치하는 모든 키를 반환합니다. 이 작업의 시간 복.. SNS 서비스 | 9. 피드 삭제 스케줄러 피드 삭제 스케줄러사용자는 피드를 조회할 때 마다, Sorted Set 자료구조인 user_activity를 key로 갖는 집합의 value에 userId를, score로 현재 시각인 유닉스 타임스탬프 10자리를 저장합니다. 일정 주기로 동작하는 스케줄러는, ZRANGEBYSCORE 커맨드를 이용해 활동을 오래 하지 않은 사용자를 검색할 수 있습니다. 예를 들어 한달 간 활동하지 않은 사용자를 검색해야할 경우 0을 min으로, 한달 전 타임스탬프 값을 max로 설정할 수 있습니다. 검색한 userId 집합은 피드 key 형태로 변환된 컬렉션으로 저장 후, DEL 커맨드를 이용해 해당하는 유저의 피드를 삭제할 수 있습니다. 피드를 삭제한 후 ZREMRANGEBYSCORE를 이용해 user_activity.. SNS 서비스 | 8. Redis를 활용한 피드 조회 시스템 기존 MySQL을 이용해 피드를 임의로 추출하는 쿼리 방식은 필연적인 디스크 I/O를 유발했습니다. 뿐만 아니라 사용자의 게시글 조회 여부와 관계 없이 조건에 부합하는 모든 게시글을 조회하기 위해 데이터베이스에 부하를 주게 됩니다. 이 과정에서 사용자의 팔로잉 사용자를 찾는 과정, 그 사용자의 게시글을 찾는 과정, 게시글이 반환될 피드의 조건에 부합하는지 필터링하는 과정은 복잡한 조인 비용 뿐만이 아닌, 임시 테이블과 파일 소트로 인한 메모리 압박이라는 문제가 있습니다. 앞서 레디스를 활용한 피드 발행 시스템을 구현했습니다. 사용자가 게시글을 작성하면, 해당 게시글이 팔로워들의 피드에 자동으로 전파됩니다. 이로 인해 사용자는 피드를 조회할 때 팔로잉 정보를 별도로 찾는 연산을 수행할 필요가 없습니다. 또.. SNS 서비스 | 7. Redis를 활용한 피드 발행 시스템 피드 저장 자료구조 먼저 피드를 저장할 자료구조를 선택해야 합니다. 사용자 ID를 피드의 key 값으로 가지며, value로서 item을 여러 개 저장할 수 있는 자료구조가 적합할 것입니다. 또한 최신 게시글이 피드 상단에 노출되야 하므로 최신 순 정렬이 필요합니다. Sorted set 자료구조를 먼저 살펴보겠습니다. 피드는 feed:{userId}의 key와 postId의 집합을 value로 가질 수 있습니다. score로 10자리 숫자의 초 단위 TimeStamp 또는 Auto Increment로 생성되는 postId를 가질 수 있습니다. 이 자료구조의 장점은 socre 기반으로 value가 정렬되므로 매우 정확한 정렬 기준을 가진다는 것입니다. 피드를 조회할 떄 ZREVRANGE를 통해 페이징 기반.. SNS 서비스 | 6. Local Cache vs Global Cache In-Memory Database의 방식 중에서도 Local Cache를 이용할 것인지, 중앙 서버를 통한 Global Cache를 이용할 것인지에 따라 나뉩니다. 각자 장단점이 존재합니다.Local Cache각 애플리케이션 서버가 자신만의 메모리 영역을 가지고 데이터를 관리하는 방식입니다. 이 방식은 네트워크 호출이 없어 매우 빠른 응답 속도를 보장하며, 외부 의존성이 없어 안정적인 서비스 운영이 가능합니다. 그러나 서버 간 데이터 정합성을 맞추기 어렵고, 메모리 사용량이 각 서버마다 중복되어 전체적인 비용이 증가할 수 있다는 단점이 있습니다. 모든 사용자들에게 동일하게 보이는 Universal Data를 저장할 경우 서버 간 데이터 동기화를 위해 Redis Pub/Sub과 같은 이벤트 기반 통신이 필.. SNS 서비스 | 5. In-Memory Database SNS 서비스에서 피드는 중요한 기능입니다. 사용자들의 활발한 상호작용을 지원하고 실시간성을 보장해야 하는 피드 시스템에서 피드 조회 시 응답 시간은 중요한 성능 요소입니다. 하지만 기존 MySQL을 통해 피드를 추출하는 방식은 필연적으로 디스크 I/O를 유발합니다. 이에 On-Disk Database와 In-Memory Database의 차이점을 알아보겠습니다.On-Disk DatabaseOn-Disk Database 에서 데이터는 영구적으로 디스크에 저장됩니다. 자주 사용되는 데이터는 캐싱되어 메모리에 올라와 있는 경우도 있지만, 그렇지 않은 데이터를 찾고자 할 때는 직접 디스크에서 데이터를 검색하는 과정을 거쳐야 합니다. 디스크에 저장된 데이터는 바로 찾을 수 없으며, 디스크의 데이터를 페이지 단위.. SNS 서비스 | 4. MySQL Master - Slave API 서버는 단순히 트래픽을 처리할 수 있는 인프라를 증설하는 것으로 충분하지만, DB의 경우에는 모든 DB 서버가 동일한 데이터를 저장하고 조회 시에도 동일한 결과를 반환해야 하는 데이터 정합성이 핵심입니다.이에 데이터가 저장되는 주체와, 저장한 데이터를 받아와 동기화시키는 Master- Slave 구조를 이용하기로 하였습니다. 쓰기 작업은 Master 서버에서 이루어지고, 읽기 작업은 Slave 서버에서 이루어지게 하여 부하를 효율적으로 분산시킬 수 있기 때문입니다. 복제 타입복제 타입 중 바이너리 로그 파일 위치 기반 복제 방식은 복제에서 각각의 이벤트들이 바이너리 로그 파일명과 파일 내 위치 값의 조합으로 식별됩니다. 문제는 이 같은 식별이 바이너리 로그 파일이 저장돼 있는 마스터 서버에서만 유.. SNS 서비스 | 3. 서버의 수평적 확장 테스트 환경docker의 리소스 제한을 이용해 cpuset을 각 2개로 분리하고 memory를 4GB 할당한 API 서버와 DB로 테스트를 진행했습니다.사용자 생성:테스트 주체 사용자 1,000명인플루언서 50명일반 사용자 2,000명팔로우 관계 설정:모든 테스트 주체 사용자가 인플루언서 전체 팔로우테스트 주체 사용자 당 일반 사용자 2,000명 중 250명 랜덤 팔로우게시글 생성: 3일 전 ~ 현재 랜덤 시각인플루언서: 각 3개씩 (총 150개)일반 사용자: 30%가 1개씩 (약 600개)게시글 세부사항:인플루언서 게시글: 미디어 10개, 댓글 100개, 좋아요 1,000개일반 사용자 게시글: 미디어 5개, 댓글 5개, 좋아요 30개JMeter 테스트 시나리오Thread Group : (n) CSV D.. 이전 1 2 다음