13. 대규모 서비스의 특성
Elastic
트래픽이나 상황에 따라서 서버의 추가/제거가 쉬워야 한다.
Resiliency
특정 장비의 장애 등은 자동으로 복구가 되어야 한다.
서버가 복구되는 건 아님
해당 장비의 장애로 인해 다른 쪽이 영향 받지 않아야 함
37. API 서버
API 서버에만 부하가 몰리는 작업은 어떤 것이 있을까?
파일 IO가 많은, 정적 파일 서빙
웹 스크래핑과 같은 디비 작업 자체보다는 다른 작업이 많은 녀석들
독립적인 작업이 가능한데, CPU나 다른 작업이 많이 필요한
LOL, 배그같은 MO 게임서버
이미지의 영상 인식이나 전처리 이런것도…
38. DB 서버
카톡방의 대화는?
페이스북의 글, 댓글, 친구 관계?
유투브 등에 올라가는 비디오나 댓글등
생각보다 우리가 아는 대부분이 여기에 부하를 줌.
46. Stateless 한 서버의 경우
장점
추가/삭제가 간단함.
사용하는 쪽에서 주소만 추가하거나 제거하는 걸로 가능
Or 로드밸런서에 추가하거나 제거 하기만 하면 OK
단점
결국 데이터의 저장이 필요하므로, 뒤에 책임을 떠 넘기는 구조임.
개별 성능은 Stateful 한 경우보다 떨어질 수 있음
47. 그런데 왜 Stateless 인가?
Stateless 한 서버에 신경을 쓰지말고
중요한 DB(Storage) 쪽에 집중을 하는게 더 좋다라는 판단.
두 마리 토끼를 다 쫓지 말고, 한 놈만 팬다.
67. Indexed
특정 데이터의 위치를 가리키는 서버가 존재
Server #1 Server #2 Server #3
User #1
Index
User #1 -> 3
User #100 -> 1
User #102 -> 1
User #100
User #102
68. Complexed
Master
Index
User RANGE #1 -> 1
Slave Slave
Master
Slave Slave
Master
Slave Slave
ONLY WRITE
ONLY READ
User RANGE #10 -> 1
User RANGE #20 -> 3
83. Consistent Hashing 의 구현 #1
Hash(key) value
Hash(server_1) 100
Hash(server_2) 200
Hash(server_3) 300
동일한 Hash 함수를 사용한다면, 같은 KEY에 대해서 Value가 바뀌는 경우가 있을까?
84. Consistent Hashing 의 구현 #2
Hash(key) value Server
Hash(Key_1) 50 Server_1
Hash(server_1) 100
Hash(Key_2) 150 Server_2
Hash(server_2) 200
Hash(Key_3) 230 Server_3
Hash(Key_4) 270 Server_3
Hash(server_3) 300
Hash(Key_5) 350 Server_1
해쉬 값이 자기보다 큰거나 같은 서버들 중에서 가장 가까운 서버로 KEY가 할당됨
85. 메일서비스를 한 번 설계해봅시다.
사용자가 가입하는 경우
사용자가 메일을 수신하는 경우
사용자가 메일 리스트를 보는 경우
사용자가 메일의 상세 내용을 보는 경우
86. 전체 가정
사용자의 메일 정보는 다음과 같이 각각 분리되어 있다.
사용자의 메일 수신 리스트
각 메일의 실제 파일 내용
한 계정의 메일 목록 정보는 모두 같은 DB 안에 존재한다.
즉 한 계정의 정보는 분산되지 않는다.
EML을 저장하는 부분은 AWS S3 같은 서비스를 이용한다고 가정합니다.
여기서 설계나 구조를 현재는 다루지 않습니다.
87. 사용자가 가입하는 경우 #1
어떤 방식을 고려할 것인가?
Range
Modular
Indexed
88. 사용자가 가입하는 경우 #2
한국의 사용자는 많아도 5천만명, 계정을 3~4개씩 만든다고 하더라도
2억개 정도
메모리가 충분한 DB한대로 충분히 커버가 되는 수준
계산 방법
이메일 주소 : 256 bytes 그 외 추가 정보로 1개당 1024 bytes 라고 가정
1024 * 2억 = 190기가 정도면 모두 메모리에 저장됨.(디스크에 갈 일도 없음.)
8:2 법칙에 의해서 20% 정도가 빈번하게 액세스 된다고 하면 190 * 0.2 = 38G
64G 정도 메모리 머신이면 aws m4.4xlarge 정도 시간당 $1, 한달에 $720 정도 듬.
장애 대비하면 720 * 2 = $1440 정도로 구성 가능(Index 서버만)
실제로 1k 도 안될 가능성이 크므로 더 작게도 구성이 가능함.
89. 사용자가 가입하는 경우 #3
사용자의 메일서비스에 가입할 때, 사용자의 메일 리스트를 저장
할 서버는 현재 서비스 중인 서버들 중에서 가장 사용량이 적은 서
버로 선택
사용량이 적은 서버
디스크 사용량, CPU 사용량이 적은 서버
가장 할당된 사용자가 적은 서버) 서버 평균 사용량(100이 한계라고 가정)
A 100
B 90
C 70
D 20
90. 사용자가 가입하는 경우 #4
User Table Schema
컬럼명 추상타입 비고
user_id Long(64bit) 유니크 고유 아이디(각 DB별)
email String 이메일 주소
shard Long 자신의 메일 리스트를 저장한 서버 번호
type int 활성화 유저인지, 아니면 다른 특징정보
created_at timestamp 계정 생성시간
last_login_time timestamp 최종적으로 로그인한 시간
91. 사용자가 메일을 수신하는 경우 #1
가정
수신받는 메일 도메인은 하나로 가정한다.(사실 여러 개라도 상관은 없다.)
메일 내용(EML)은 DB가 아닌 다른 곳에 저장된다.
AWS의 S3 같은 것을 생각하자.
메일을 가져가는 방법은, 일단 수신 받은 시간 순으로만 된다고 가정한다.
송신자 순, 메일 제목 순, 이런 건 고려하지 않는다.
92. 사용자가 메일을 수신하는 경우 #2
Mails Table Schema
컬럼명 추상타입 비고
mail_id Long(64bit) 유니크 고유 아이디(각 DB별)
receiver String or Long 수신자
sender String or Long 송신자
subject String 메일 제목
received_at timestamp 수신 시간
eml_id String or Long 메일 본문 저장 id(or url)
is_read boolean 읽었는지 여부
contents String 보여줄 내용의 일부?(중요하지 않음)
93. 사용자가 메일을 수신하는 경우 #3
송신자
메일 서버
수신자
메일 서버
메일 전송
메일 수신
User
Service
정상 유저 확인
메일 파싱
메일 메타 정보 저장
DB #1 DB #2 DB #3
Eml
Storage
Eml
Storage
Eml
Storage
eml
Storage
메일 본문 정보 저장
이해를 돕기 위한 아주 추상적인 구조입니다.
94. 사용자가 메일을 수신하는 경우 #4
EML 저장을 위한 서비스가 추가로 필요.
AWS S3 같은 것을 이용한다고 하더라도
결국 해당 EML 파일에 대한 key를 무엇을 할 것인지가 중요함.
EX)
Unique 한 값을 만들어낼 수 있어야 한다.
{receiver_id}_{mail_id}
Mail_id 자체로는 나눠진 shard 마다 중복이 존재 가능함.
{receiver_id}_{mail_id}는 Unique
95. 사용자가 메일 리스트를 보는 경우
사용자
Mail
Service
목록 요청
목록 전송
User
Service
정상 유저 확인
메일 리스트 요청
select * from mails where receiver=charsyam order by created_at
desc
DB #1 DB #2 DB #3
이해를 돕기 위한 아주 추상적인 구조입니다.
charsyam: 3
charsyam
메일 리스트 전달
96. 사용자가 메일의 상세 내용을 보는 경우
사용자
Mail
Service
이해를 돕기 위한 아주 추상적인 구조입니다.
charsyam_1
메일 요청
eml_id 전달
메일 상세
전달
Eml
Storage
Eml
Storage
Eml
Storage
eml
Storage
97. 메일 EML을 저장하는 KEY
EML ID를 왜 {receiver}_{mail_id} 로 했을까?
KEY를 만드는 방법은 굉장히 다양할 수 있음.
좀 더 좋은 KEY를 만들 수 있을까?
98. 질문
EML ID 필드가 필요할까요?
이미 receiver 와 mail_id가 있으므로 그냥 조합하면 되지 않을까?
데이터를 다른 서버로 이전해야 하는 경우?
111. 필요 정보들
시간정보(Timestamp)
Timestamp 는 1970년 1/1일 기준, 우리는 2018년 부터 시작해도…
언제까지의 시간 정보가 필요할까?
4byte를 다 쓰면 2106년 2/7일 06:28분 까지 커버됨(32bit)
채팅방 정보
Shard 정보
113. KEY의 설계 #1
Simple 버전
64bit = 8 bytes
기존 userid 를 생성되는 key 와 붙여서 사용하는 방법
6209324585984
Timestamp = 6209324585984 >> 12 =
1515948385
Sequence = 6209324585984 & 0xFFF = 1024
charsyam_ 6209324585984
Timestamp sequence
52 bits 12 bits = 4096
114. KEY의 설계 #2
Client Service
KEY 전송 User
Service
정상 유저 확인
KEY 파싱
DB #1 DB #2 DB #3
이해를 돕기 위한 아주 추상적인 구조입니다.
charsyam_6209324585984 charsyam
Shard : 3
KEY 6209324585984 요청
각 유저의 데이터는 각 유저가 지정된 Shard
이외에는 저장될 수 없다.
117. KEY의 설계 #4
Client Service
KEY 전송
KEY 파싱
DB #1 DB #2 DB #3
이해를 돕기 위한 아주 추상적인 구조입니다.
6209324585984
KEY 6209324585984 요청
6209324585984 = Shard ID 2048
Shard Server
……. ……
…… DB #1
2048 DB #2
…… DB #3
…… ……
Check Shard Map
133. Zookeeper 의 특징
절대로 죽지않는다.(거짓말)
잘 안죽는다.(몇대 죽어도 상관은 없다.)
그러나 다 죽을때도 종종 있음.
임시 노드의 경우, Health Check를 통해서 자동적으로 접속된 노
드가 사라지면 데이터가 사라진다.(30초가 기본…)
Cluster Membership
노드의 순서를 보장해준다.
Leader Election
146. Cluster Membership
Cases
API Server 가 추가/변경 되었다.
Database Master 장비가 추가/변경되었다.
Cache 장비가 추가/변경 되었다.
우리의 대응은?
목록을 추가하고, 배포해야 합니다.
목록만 추가하면 알아서 동작합니다.
장비만 추가하면 알아서 동작합니다.
148. Zookeeper Event Notification #1
zookeeper
예약 서버
예약 서버
예약 서버결제 서버
결제 서버
/znode/payment/
znode_0000001
znode_0000002
서버 시작시
/znode/payment/
에 임시 노드 등록
149. Zookeeper Event Notification #1
zookeeper
특정 znode 변경
서버 추가/삭제/변경
예약 서버
예약 서버
예약 서버결제 서버 #1
결제 서버 #2
/znode/payment/
znode_0000001
znode_0000002
결제 서버 #2
znode_0000003
특정 node 변경 이벤트
/znode/payment/
를 다시 읽어서 서버로
접속
156. 동료들에게 올바른 질문하기
질문을 하기 위해서…
문제의 증상을 정리
어떤 오류가 나오는지
자신이 정말 알고자 하는 것…
자신이 시도한 방법…
157. 올바른 답변 적용하기
알려준 방법으로 문제가 해결된다면
문제의 근본적인 원인은 무엇인가?
알려준 해결책은 어디에 적용되는가?
옵션을 추가하세요.
그 옵션을 알고만 끝날 것인가?
그 옵션이 어떻게 동작하는지를 완전히 이해하고 유사한 문제를 해
결 할 수 있을것인가?
159. 문서화와 공유
내가 문제를 해결한 것만으로는 모든 것이 해결될까?
내가 해결한 방법으로 팀의 누구나 해결할 수 있다면?
나는 이제 이 문제를 던지고 새로운 재미난 문제로…
문서화
원인/증상/해결책(Opertaion)
그리고 공유
발표 및 문서 위치 공유