1. 요구사항 정리
1.1. 기능적 요구사항
•
이메일 발송/수신
•
모든 이메일 가져오기
•
읽음 여부에 따른 이메일 필터링
•
제목, 발신인, 메일 내용에 따른 검색 기능
•
스팸 및 바이러스 방지 기능
•
지원 프로토콜은 HTTP로 사용
1.2. 비기능적 요구사항
•
안정성 - 이메일 데이터가 소실되서는 안된다.
•
가용성 - 사용자 데이터를 여러 노드에 자동 복제하고 일부 노드에 장애가 발생해도 작동해야함
•
확장성 - 사용자가 늘어나도 감당할
•
유연성 - 새로운 컴포넌트를 더해 기능 확장이 가능해야 한다.
1.3. 개략적 규모 추정
•
10억 명의 사용자
•
한 사람이 보내는 평균 이메일 수 = 10건
◦
이메일 전송 QPS = 10^9 * 10 / 10^5 = 100,000
•
한 사람이 수신하는 메일 수는 40건
•
하나의 메타데이터는 평균 50KB
◦
10억 명 사용자 * 하루 40건 이메일 * 365일 * 50KB = 730PB
2. 청사진 그리기
•
이메일 교환기 레코드로 DNS 서버에 등록하여 레코드를 검색할 수 있도록 한다.
•
첨부파일은 Base64 인코딩을 사용하여 첨부된다.
◦
첨부파일은 20~25M로 크기를 제한한다.
•
전통적 이메일은 다음 시퀀스 다이어그램으로 작동한다.
sequenceDiagram 전송자->>전송자SMTP서버: 이메일 전송 전송자SMTP서버->>전송자저장소: 데이터 저장 전송자SMTP서버->>수신자SMTP서버: 이메일 수신 수신자->>수신자IMAP/POP서버: 메일가져오기 수신자SMTP서버->>수신자저장소: 메일데이터 저장 수신자IMAP/POP서버->>수신자저장소: 데이터 검색 수신자저장소-->>수신자IMAP/POP서버: 데이터 전달 수신자IMAP/POP서버-->>수신자: 메일데이터 전송
Mermaid
복사
•
전통적 아키텍처는 파일 시스템 디렉터리를 사용한다.
◦
해당 목적으로 Maildir이라는 이름의 디렉터리가 널리 사용됨
2.1. 분산 메일 서버
•
기본적으로 SMTP/POP/IMAP 등을 대체할 수 있는 HTTP API를 제공해야 한다.
•
첨부파일 저장소는 무적의 S3를 사용하도록 하겠다.
◦
NoSQL은 적합하지 않은 이유로 첨부파일 저장시 레코드 캐시 사용이 어렵다.
•
최근 수신된 이메일은 자주 읽을 가능성이 높으므로 캐싱해두기로 하자
•
고속텍스트 검색을 위한 역인덱스 자료구조로 만들어진 분산 문서 저장소를 사용한다.
2.1.1. 이메일 전송 절차
•
웹서버는 이메일 검증(미리 정의된 규칙, 바이러스, 스팸 검사)과 저장 사이의 역할을 담당한다.
2.1.2. 이메일 수신 절차
•
이메일의 첨부 파일이 큐에 들어가기에 너무 큰 경우 첨부파일 저장소에 보관
3. 설계
•
이메일 메타데이터가 가지는 특성
◦
이메일의 헤더는 일반적으로 작고 빈번하게 이용됨
◦
일반적으로 사용자는 이메일을 한번만 읽음
◦
각 이메일의 액션은 사용자 별로 격리 수행되어야 한다.
◦
높은 데이터 안정성을 보장해야 한다.
•
올바른 데이터베이스 선정
◦
RDB
▪
RDB는 데이터 크기가 작을때 효율적이다.
▪
이메일은 자료가 크기 때문에 질의가 비효율적이다.
▪
BLOB자료형에 접근할 때마다 많은 디스크 I/O가 발생하기 때문에 RDB는 바람직하지 않다
◦
분산 객체 저장소
▪
이메일 원시 데이터를 S3에 저장하는건 어떨까?
▪
데이터 보관에는 매우 적합하다.
▪
이메일의 표시, 키워드 검색, 이메일 타래 등의 기능 구현엔 적합지 않다.
◦
NoSQL
▪
구글 지메일은 빅테이블을 저장소로 사용한다.
•
요건 프라이빗 소스라서 상세구현은 모른다~
▪
이메일 서비스 제공 업체 중 카산드라를 사용하는 곳은 확인된바가 없다.
•
데이터는 파티션/클러스터 키로 구분된다
◦
파티션 = 유저 아이디
▪
모든 노드에 균등하게 분산되도록 파티션키를 구한다.
◦
클러스터 = 같은 파티션 내 정렬 데이터
•
데이터 계층이 지원해야 하는 질의
◦
주어진 사용자의 모든 폴더를 구한다.
◦
특정 폴더 내의 모든 이메일을 표시한다.
◦
메일을 새로 만들거나, 삭제하거나, 가져온다.
◦
이미 읽은 메일 전부, 또는 아직 읽지 않은 메일 전부를 가져온다.
◦
보너스 점수를 받을 수 있는 질의: 이메일 타래를 전부 가져온다.
3.1. 고속 텍스트 검색을 위한 방안
•
엘라스틱 서치
◦
메일 전송/수신/삭제 시 비동기적으로 엘라스틱 서치와 동기화한다.
◦
사용자 검색시엔 동기적으로 결과를 반환한다
•
맞춤형 검색 솔루션
◦
색인 구축 프로세스는 LSM 트리를 사용하여 디스크에 저장되는 색인을 구조화 하는 것이 바람직한 전략일 것이다.
◦
쓰기 경로는 순차적 쓰기 연산만 수행하도록 최적화
◦
해당 구조는 빅테이블, 카산드라의 핵심구조다!
◦
메모리에 보관된 데이터의 양이 사전에 정의된 임계치를 넘으면 데이터는 다음 계층으로 병합된다.