Open skarltjr opened 2 years ago
챕터 1. 서비스 규모 확장
수직적 규모 확장 / scale up
- 말 그대로 서버의 성능을 증가시키는 것
- 트래픽의 양이 적을 때 좋으며 특히 단순함이 가장 큰 장점
- ★그러나 수직전 확장에는 한계가 존재
- 성능 증가는 한계가 존재하며 서버에 장애가 발생하면 서비스가 완전히 중단된다.
수평적 규모 확장
- 대규모 서비스는 위와같은 이유로 수평적 규모확장이 효율적
로드밸런서는 트래픽을 여러 서버에 분산시킨다.
만약 하나의 서버가 다운돼도 다른 서버로 트래픽을 전달하고 그 동안 고장난 서버를 복구시킬 수 있다.
대부분의 서비스에서 읽기가 많이 발생할까? 아니면 쓰기가 많이 발생할까?
거의 모든 서비스에서 읽기가 더 많이 발생할것이고 이것이 핵심이다
주 데이터베이스와 / 여러개의 부 데이터베이스를 활용한다
쓰기 -> 주 데이터베이스 -> N개의 부 데이터베이스 <- 읽기 <- 유저
쓰기(write update delete )는 주 데이터베이스에서만 가능하도록하여 수행하고 원본은 이곳에 저장 읽기는 부 데이터베이스에서 수행하며 주 데이터베이스에 쓰여진 원본의. 사본을 전달받아 저장 후 읽기 시 이를 전달
장점 :
찾고자하는 데이터가 캐시에 저장되어 있다면 바로 반환해준다.
만약 없다면 데이터베이스에서 찾아와 이를 캐시에 저장한 후 반환한다.
캐시는 데이터베이스보다 훨씬 빠르게 동작한다.
그러나! 캐시를 사용하기전 고려사항이 있다.
does not go for the update, but goes for the lazy strategy
내가 데이터를 요청한 순간 이전 마지막으로 업데이트된 데이터를 가져오는걸 보장해줄 수 있다고 생각한다
이전
데이터를 받는것이라고 생각앞서 트래픽을 여러 서버로 분산시키위해 앞단에 로드밸런서를 위치시킨다고했다.
여기서 만약 ★모든 서버가 데이터를 저장하는 stateful상태라면?
a 클라이언트에 대한 요청은 반드시 해당 클라이언트 정보를 갖고있는 A서버가 일대일 처리를해야한다
B서버는 a 클라이언트의 정보를 모르니 처리해줄 수 없다. 즉 확장의 한계를 가져다준다.
여기서 만약 모든 서버가 stateless고 중요데이터는 그 뒷단에 db에 저장한다면 어떠한 클라이언트가 요청을해도 모든 서버가 이를 처리해줄 수 있다.
producer라는 입력 생산 서비스가 메세지를 만들고 이를 큐에 발행
큐와 연결된 consumer 서비스가 큐에서 메세지를 꺼내 이를 처리
큐와 연결된 여러 consumer를 통해 하나의 consumer가 죽더라도 다른 consumer가 이를 처리해줄 수 있다. 또한 consumer가 죽더라도 입력 서비스는 살아있고 메세지를 생산하여 큐에 저장해놓을 수 있다. 이 경우 consumer가 살아나면 이를 처리해줄 수 있다.
추가로 시간이 오래 걸리는 처리과정은 이러한 메세지큐를 통해 비동기로 효과적으로 처리할 수 있다. 물론 큐가 커지면 이를 빠르게 처리하기위해선 더 많은 consumer가 필요하다
### 로그 & 매트릭
- 로그 : 에러 로그를 모니터링하는것은 중요하다. 시스템의 오류와 문제를 보다 쉽게 찾아낼 수 있다.
- 매트릭 : cpu 메모리 등의 정보로 시스템의 현재 상태를 파악하기 좋다.
- 앞에서 확장에 대해 얘기하며 항상 한 말은 서버가 죽어도 다른 서버가 처리할 수 있다는 말이었다.
- 개인적인 생각으로 이 서버가 죽었다는 말은 곧 서버가 왜 죽었는지를 파악하고 다시 살려야한다는 말이라고 생각
- 이를 위해 로그나 매트릭 정보가 필요하며 이 정보들을 저장할 필요가 있다고 생각
- ★ 쿠버네티스를 학습하며 이러한 경험을 해본적이 있다.
- 간단하게 filebeat 컨테이너를 활용하여 /var/log/nginx/error.log에 저장되는 nginx 에러로그를 수집
- 이를 엘라스틱서치에 저장한 후 키바나를 통해 시각화
- 이를 통해 어느 시점에 에러가 발생하며, 그 기록이 무엇인지를 파악할 수 있었다.
- https://github.com/skarltjr/Kubernetes-with-Docker/tree/main/쿠버네티스_dev(4)
- https://github.com/skarltjr/Kubernetes-with-Docker/tree/main/쿠버네티스_dev(5)
### 데이터베이스의 규모 확장
- 데이터베이스 또한 수직적 vs 수평적으로 확장할 수 있는데
데이터베이스의 수직적 확장 수직적 확장 방법에는 심각한 약점이 존재.
수평적 확장
수평적 확장은 샤딩이라고도 부르는데 대규모 데이터베이스를 샤드(shard)라는 작은 단위로 분할하여 저장
모든 샤드는 같은 스키마를 사용하지만 각 샤드에 보관되는 데이터는 중복 x
ex) 아래처럼 number가 2보다 작은건 a 데이터베이스 / 2보다 큰것들은 b데이터베이스에 보관
- 여기서 샤딩 키(sharding key)는 user_number
- 추가적으로 이 경우 sharding key를 인덱스로 하여 특정 데이터를 검색할 때 더 빠른 속도로 가능
- 만약 user_number가 1인애를 찾겠다고하면 2보다 작으니 바로 a데이터베이스로 접근하여 탐색
샤딩에서도 고려해야할 문제점은 존재한다.
데이터의 재 샤딩 (re-sharding) :
- 만약 데이터가 너무많아서 이들을 구분하기 위한 추가적인 샤드 키를 추가하여 더 쪼거나
- 특정 샤드에만 데이터가 집중되면 샤드 키를 계산하는 함수를 변경하여 데이터를 재배치한다.
hotspot key :
- 특정 샤드에 쿼리가 집중되는 경우도 존재할 수 있다.
- 예를들어 나이가 샤딩키인 경우 특히 20세 이상에 대해 쿼리가 너무많은 경우 더 잘게 쪼개야 할 수도 있다.
조인과 비정규화 :
- 하나의 데이터베이스를 여러 샤드로 쪼갰다.
- 그럼 당연하게도 여러 샤드에 걸친 데이터를 조인하기가 힘든데
- 이를 해결하는 방법 중 하나는 데이터베이스의 비정규화
1. 웹 계층은 stateless하게
2. 모든 계층은 다중화를 통해 안정성 확보
3. db접근을 줄이기위한 캐싱 고려
4. 시스템을 지속적으로 모니터링
챕터 2. 개략적인 규모 측정
1024 Byte => 1 킬로 바이트(Kilo Byte;KB), 2의 10승(2^10 = 10^3)
2^10 = 1,024 Byte
1024 KB => 1 메가 바이트(Mega Byte;MB), 2의 20승(2^20 = 10^6)
2^20 = 1,048,576 Byte
1024 MB => 1 기가 바이트(Giga Byte;GB), 2의 30승(2^30 = 10^9)
2^30 = 1,073,741,824 Byte
1024 GB => 1 테라 바이트(Tera Byte;TB), 2의 40승(2^40 = 10^12)
2^40 = 1,099,511,627,776 Byte
1024 TB => 1 페타 바이트(Peta Byte;PB), 2의 50승(2^50 = 10^15)
2^50 = 1,125,899,906,842,624 Byte
이를 정리해보면
1. 메모리는 빠르지만 디스크는 느리다
2. 디스크 탐색은 가능한 피하라
3. 데이터 센터는 보통 여러 지역에 분산되어 있고 이들간에 데이터 전달은 시간이 매우 소요된다.
신기한 점
이 책에서 말하는 데이터센터는 아래 그림과 같은 구조를 말한다
그럼 데이터 센터 내에서의 메시지 왕복시간은 서버 < - > 데이터베이스도 포함이라고 생각하는데
이 시간보다 컴퓨터 디스크에서의 탐색이 더 많은 시간을 잡아먹는다는것이 놀라웠고 그만큼 디스크 탐색이 오랜 시간을
잡아먹기때문에 피해야한다고 느꼈다.
또한 내부의 캐시의 성능이 매우 효과적이라는것도 느낄 수 있었다.
챕터 5. 안정 해시 설계
안정 해시는 : 해시 테이블 크기가 조정될 때 평균적으로 k/n개의 키만 재배치하는 기술
4개의키가 존재했다가 s1(1번 서버)가 죽은경우 4 / 3 = 1개의 키만 재배치
여기서는 s1로 향하던 키 하나를 s2로 향하도록 조정
★나머지 키는 영향 x
서버 추가도 마찬가지로 하나의 키만 재배치된다.
s0으로 향하던 키 k0가 이제부터는 새로 추가된 서버 s4를 향한다.
문제 1.
서버가 추가되거나 삭제될 수 있는데 문제는 이 추가 & 삭제로 서버 파티션이 변동적
ex) 0번 서버를 삭제(죽으면)하면 0을 향하던 k0이 s1을 향하고 s1은 s0가 담당하던 크기만큼 추가로 감당해야한다.
문제 2.
★ 키의 균등 분포 달성이 어렵다.
결국 기본 구현법은 시계방향으로 진행되고 아래같은 상황이 만들어질 수 있다.
대부분 키가 서버2를 향하고 / 서버 3은 어떤 값도 들어오지않는다. 사용되지 않는다.
![KakaoTalk_Photo_2022-02-03-21-50-13](https://user-images.githubusercontent.com/62214428/152346465-40b22aab-11ec-4bca-9f34-020b6b31e2ae.jpeg)
★가상 노드의 개수를 늘리면 키의 분포가 점점 더 균등해진다.
k/n개를 재배치해야한다. 그런데 무엇을?
안정 해시의 이점
- 서버가 추가되거나 삭제될 때 재배치되는 키의 최소화
- 균등 분배를 통한 수평적 확장 보완
- 균등분배는 곧 hotspot문제 해결
- ex) 특정 데이터베이스 샤드에 집중되는 문제 해결
https://book.naver.com/bookdb/book_detail.nhn?bid=20756755 도서를 읽고 정리한 이슈