# Pinterest가 6명의 엔지니어만으로 1100만명의 사용자로 확장한 방법

> Clean Markdown view of GeekNews topic #11825. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=11825](https://news.hada.io/topic?id=11825)
- GeekNews Markdown: [https://news.hada.io/topic/11825.md](https://news.hada.io/topic/11825.md)
- Type: news
- Author: [xguru](https://news.hada.io/@xguru)
- Published: 2023-11-13T10:45:01+09:00
- Updated: 2023-11-13T10:45:01+09:00
- Original source: [engineercodex.substack.com](https://engineercodex.substack.com/p/how-pinterest-scaled-to-11-million)
- Points: 41
- Comments: 1

## Topic Body

### 교훈들  
- 잘 알려진, 검증된 기술 사용   
- Keep it Simple   
- 너무 창의적으로 생각하지 않기(동일한 노드를 추가하여 확장가능한 아키텍처로 결정)  
- 옵션을 제한하기   
- DB 샤딩 > 클러스터링   
- 즐겁게! (신입 엔지니어도 첫주부터 코드에 기여 가능)  
### 2010년 3월: 클로즈 베타, 엔지니어 1명   
- MySQL 1대 + 웹서버(Django + Python) 1대 + 엔지니어 1명(2 명의 공동창업자 포함). Rackspace에 호스팅   
### 2011년 1월: 1만명 사용자(MAU), 엔지니어 2명   
- AWS EC2 웹 서버 스택(EC2 + S3 + CloudFront)   
- Django + Python   
- Redundacy를 위한 4대의 웹서버   
- NGINX 를 리버스 프록시이자 로드 밸런서로   
- MySQL 1대에 Read-only 세컨더리 1대   
- Counter 용 MongoDB   
- 1개의 태스크 큐와 2대의 태스크 프로세서(비동기 작업)   
### 2011년 10월: 320만 MAU, 엔지니어 3명   
- 10개월간 급속도로 성장해서 1.5달에 2배씩 사용자가 늘어남   
- 2011년 3월 아이폰 앱 출시가 성장을 주도한 것중 하나   
- 빠르게 성장하면서 기술 쪽 문제가 더 자주 발생   
- 핀터레스트는 이때 실수를 함 : "아키텍처를 지나치게 복잡하게 만들었음"   
- 엔지니어가 3명밖에 없는데, 데이터에 사용하는 DB 기술이 5가지였음   
- 수동으로 MySQL을 샤딩하면서 동시에 Cassandra 와 Membase(현재 Couchbase)를 사용하여 데이터를 클러스터링함   
- 그들의 "너무 복잡한 스택"  
  - 웹서버 스택(EC2 + S3 + Cloudnfront)   
    - Flask(Python)으로 백엔드를 옮기기 시작   
  - 웹서버 16대   
  - API 엔진 2대   
  - NGINX 프록시 2대   
  - 수동으로 샤딩된 5대의 MySQL DB + 9대의 읽기 전용 세컨더리   
  - 카산드라 노드 4개   
  - Membase 노드 15개(3개의 별도 클러스터)  
  - Memcache 노드 8개   
  - Redis 노드 10개   
  - Task 라우터 3대 + Task 프로세서 4대   
  - Elastic Search 노드 4개   
  - Mongo 클러스터 3개   
- 클러스터링이 잘못됨   
  - 이론적으로는 클러스터링이 자동적으로 데이터스토어를 확장, 고가용성 및 로드밸런싱 해주면서 SPOF를 없애주지만  
  - 안타깝게도 실제로는 클러스터링은 너무 복잡하고, 업그레이드 메커니즘이 어려우며, 큰 SPOF 를 가짐   
  - 각 DB에는 DB에서 DB로 라우팅하는 클러스터 관리 알고리듬이 있음  
    - DB에 문제가 발생하면 새 DB가 추가되고 이를 관리해줘야 하지만   
    - Pinterest의 클러스터 관리 알고리듬에 버그가 발생해서 모든 노드의 데이터가 손상되고 데이터 리밸런싱이 중단되었으며 몇 가지 수정할 수 없는 문제가 발생  
- Pinterest의 해결책은?   
  - 시스템에서 모든 클러스터링 기술(카산드라, 멤베이스)을 제거  
  - (더 검증된) MySQL + Memcached로 올인  
### 2012년 1월: 1100만 MAU, 엔지니어 6명   
- 약 1200만 에서 2100 DAU   
- 이 시점에 아키텍처를 단순화하는데 시간을 할애함   
- 클러스터링 및 카산드라를 제거하고 MySQL, Memcache, 샤딩으로 대체   
- 단순화된 스택   
  - Amazon EC2 + S3 + Akamai (CloudFront 대체)  
  - AWS ELB (Elastic Load Balancing)  
  - 90 Web Engines + 50 API Engines (Flask 이용)  
  - 66 MySQL DBs + 66 secondaries   
  - 59 Redis Instances  
  - 51 Memcache Instances  
  - 1 Redis Task Manager + 25 Task Processors  
  - 샤딩된 Apache Solr (Elasticsearch 대체)  
  - **제거한 것들: Cassanda, Membase, Elasticsearch, MongoDB, NGINX**  
### Pinterest가 DB를 수동 샤딩한 방법   
> 데이터베이스 샤딩은 단일 데이터세트를 여러 개의 데이터베이스로 분할하는 방법  
장점: 고가용성, 로드 밸런싱, 데이터 배치를 위한 간단한 알고리듬, 데이터베이스를 쉽게 분할하여 용량 추가, 데이터 찾기 쉬움  
- 처음 샤딩했을때 문제가 있어서, 몇달에 걸쳐서 점짐적으로 수동 샤딩을 진행   
- 전환 순서   
  1. 1 DB + Foreign Keys + Joins   
  2. 1 DB + Denormalized + Cache   
  3. 1 DB + Read Slaves + Cache   
  4. 여러대의 기능적으로 샤딩된 DB들 + Read Slaves + Cache   
  5. ID로 샤딩된 DB들 + Backup Slaves + Cache   
- 데이터베이스 계층에서 테이블 조인과 복잡한 쿼리를 제거하고 많은 캐싱을 추가  
- 데이터베이스 전반에 걸쳐 고유한 제약 조건을 유지하는 데 많은 노력이 필요했기 때문에 사용자 이름과 이메일과 같은 데이터는 거대한 샤딩되지 않은 데이터베이스에 보관  
- 모든 테이블이 샤드에 올라감   
### 2012년 10월: 2200만 MAU, 엔지니어 40명   
- 아키텍처는 그대로 유지하면서, 몇대의 똑같은 시스템들을 추가   
  - Amazon EC2 + S3 + CDNs (EdgeCast, Akamai, Level 3)  
  - 180 web servers + 240 API engines (Flask)  
  - 88 MySQL DBs + 88 secondaries each  
  - 110 Redis instances  
  - 200 Memcache instances  
  - 4 Redis Task Managers + 80 Task Processors  
  - Sharded Apache Solr  
- 하드디스크에서 SSD로 옮기기 시작   
- 중요한 교훈: **제한적이고 검증된 선택(limited, proven choices)이 좋았다는 것**  
- EC2와 S3를 고수하다 보니 구성 선택의 폭이 제한되어 골칫거리가 줄어들고 단순성이 높아졌음   
- 하지만 새로운 인스턴스는 몇 초 만에 준비될 수 있게 됨. 즉, 단 몇 분 만에 10개의 멤캐시 인스턴스를 추가 가능   
### Pinterest 의 데이터베이스 구조   
- IDs   
  - Instragram과 비슷하게, 샤딩 때문에 유니크한 ID 구조를 가지고 있음  
  - 64bit ID의 구성   
    - Shard ID : 어떤 샤드인지. 16 bit   
    - Type : 객체 타입(Pin 같은 것 ) 10 bit  
    - Local ID : 테이블에서의 포지션. 38 bit   
  - 이 ID의 Lookup 구조는 그냥 간단한 파이썬 딕셔너리   
- Tables   
  - 개체 테이블과 매핑 테이블이 있었음   
  - 객체 테이블은 핀, 보드, 댓글, 사용자 등을 위한 것. MySQL Blob(JSON)에 매핑된 로컬 ID  
  - 매핑 테이블은 보드를 사용자에 매핑하거나 좋아요를 핀에 매핑하는 등 객체 간의 관계형 데이터를 위한 테이블. 전체 ID와 타임스탬프에 매핑된 전체 ID  
  - 모든 쿼리는 효율성을 위해 PK(기본 키) 또는 인덱스 조회. 모든 조인을 제거

## Comments



### Comment 20540

- Author: xguru
- Created: 2023-11-13T10:46:02+09:00
- Points: 2

[인스타그램이 오직 3명의 엔지니어로 1400만 사용자를 확보한 방법](https://news.hada.io/topic?id=10916)  
이것과 같은 시리즈의 글이면서, 내용도 연결되네요.   
"간단하게 유지할 것. 잘 알려지고, 검증된 기술들을 사용할 것"
