Pinterest ขยายสู่ผู้ใช้ 11 ล้านคนด้วยวิศวกรเพียง 6 คนได้อย่างไร
(engineercodex.substack.com)บทเรียน
- ใช้เทคโนโลยีที่เป็นที่รู้จักและผ่านการพิสูจน์แล้ว
- Keep it Simple
- อย่าพยายามคิดอะไรที่สร้างสรรค์เกินไป (เลือกสถาปัตยกรรมที่ขยายได้ด้วยการเพิ่มโหนดแบบเดียวกัน)
- จำกัดตัวเลือก
- DB sharding > clustering
- สนุกกับมัน! (แม้วิศวกรใหม่ก็สามารถมีส่วนร่วมกับโค้ดได้ตั้งแต่สัปดาห์แรก)
มีนาคม 2010: close beta, วิศวกร 1 คน
- MySQL 1 เครื่อง + เว็บเซิร์ฟเวอร์ (Django + Python) 1 เครื่อง + วิศวกร 1 คน (รวมผู้ร่วมก่อตั้ง 2 คน) โฮสต์บน Rackspace
มกราคม 2011: ผู้ใช้ 10,000 คน (MAU), วิศวกร 2 คน
- สแตกเว็บเซิร์ฟเวอร์บน AWS EC2 (EC2 + S3 + CloudFront)
- Django + Python
- เว็บเซิร์ฟเวอร์ 4 เครื่องเพื่อ redundancy
- ใช้ NGINX เป็น reverse proxy และ load balancer
- MySQL 1 เครื่องพร้อม read-only secondary 1 เครื่อง
- MongoDB สำหรับตัวนับ
- task queue 1 ตัวและ task processor 2 เครื่อง (งานแบบ asynchronous)
ตุลาคม 2011: 3.2 ล้าน MAU, วิศวกร 3 คน
- เติบโตอย่างรวดเร็วตลอด 10 เดือน โดยจำนวนผู้ใช้เพิ่มเป็น 2 เท่าทุก 1.5 เดือน
- การเปิดตัวแอป iPhone ในเดือนมีนาคม 2011 เป็นหนึ่งในปัจจัยที่ขับเคลื่อนการเติบโต
- เมื่อเติบโตเร็ว ปัญหาด้านเทคนิคก็เกิดบ่อยขึ้น
- Pinterest ทำพลาดในช่วงนี้: "ทำให้สถาปัตยกรรมซับซ้อนเกินไป"
- มีวิศวกรแค่ 3 คน แต่ใช้เทคโนโลยีฐานข้อมูลถึง 5 แบบ
- shard MySQL แบบ manual พร้อมกับใช้ Cassandra และ Membase (ปัจจุบันคือ Couchbase) เพื่อทำ clustering ของข้อมูล
- "สแตกที่ซับซ้อนเกินไป" ของพวกเขา
- สแตกเว็บเซิร์ฟเวอร์ (EC2 + S3 + Cloudnfront)
- เริ่มย้าย backend ไปใช้ Flask (Python)
- เว็บเซิร์ฟเวอร์ 16 เครื่อง
- API engine 2 เครื่อง
- NGINX proxy 2 เครื่อง
- MySQL DB 5 เครื่องที่ shard แบบ manual + read-only secondary 9 เครื่อง
- Cassandra node 4 ตัว
- Membase node 15 ตัว (3 คลัสเตอร์แยกกัน)
- Memcache node 8 ตัว
- Redis node 10 ตัว
- task router 3 เครื่อง + task processor 4 เครื่อง
- Elastic Search node 4 ตัว
- Mongo cluster 3 ชุด
- สแตกเว็บเซิร์ฟเวอร์ (EC2 + S3 + Cloudnfront)
- clustering ผิดทาง
- ในทางทฤษฎี clustering จะช่วยขยาย datastore อัตโนมัติ ให้ high availability และ load balancing พร้อมกำจัด SPOF
- แต่น่าเสียดายว่าในทางปฏิบัติ clustering ซับซ้อนเกินไป มีกลไกอัปเกรดที่ยาก และมี SPOF ขนาดใหญ่
- แต่ละ DB มีอัลกอริทึมจัดการคลัสเตอร์สำหรับ route จาก DB หนึ่งไปยังอีก DB หนึ่ง
- เมื่อ DB มีปัญหา ก็ต้องเพิ่ม DB ใหม่และจัดการมัน
- แต่ในอัลกอริทึมจัดการคลัสเตอร์ของ Pinterest เกิดบั๊ก ทำให้ข้อมูลของทุกโหนดเสียหาย การ rebalance ข้อมูลหยุดชะงัก และเกิดปัญหาบางอย่างที่แก้ไขไม่ได้
- ทางแก้ของ Pinterest คืออะไร?
- เอาเทคโนโลยี clustering ทั้งหมดออกจากระบบ (Cassandra, Membase)
- ทุ่มไปที่ MySQL + Memcached (ที่ผ่านการพิสูจน์มากกว่า)
มกราคม 2012: 11 ล้าน MAU, วิศวกร 6 คน
- DAU ราว 1.2 ล้านถึง 2.1 ล้าน
- ช่วงนี้พวกเขาใช้เวลาไปกับการทำให้สถาปัตยกรรมง่ายขึ้น
- เอา clustering และ Cassandra ออก แล้วแทนที่ด้วย MySQL, Memcache และ sharding
- สแตกที่เรียบง่ายขึ้น
- 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 แบบ sharded (แทน Elasticsearch)
- สิ่งที่เอาออก: Cassandra, Membase, Elasticsearch, MongoDB, NGINX
วิธีที่ Pinterest ทำ manual sharding ให้ DB
Database sharding คือวิธีแบ่งชุดข้อมูลเดียวออกเป็นหลายฐานข้อมูล
ข้อดี: high availability, load balancing, อัลกอริทึมที่เรียบง่ายสำหรับการจัดวางข้อมูล, แยกฐานข้อมูลเพื่อเพิ่มความจุได้ง่าย, ค้นหาข้อมูลง่าย
- ตอน shard ครั้งแรกมีปัญหา จึงค่อย ๆ ทำ manual sharding แบบค่อยเป็นค่อยไปตลอดหลายเดือน
- ลำดับการเปลี่ยนผ่าน
- 1 DB + Foreign Keys + Joins
- 1 DB + Denormalized + Cache
- 1 DB + Read Slaves + Cache
- DB หลายเครื่องที่ shard ตามหน้าที่ + Read Slaves + Cache
- DB ที่ shard ตาม ID + Backup Slaves + Cache
- เอา table join และ query ที่ซับซ้อนออกจากชั้นฐานข้อมูล แล้วเพิ่ม caching จำนวนมาก
- ข้อมูลอย่างชื่อผู้ใช้และอีเมลถูกเก็บไว้ในฐานข้อมูลขนาดใหญ่ที่ไม่ shard เพราะต้องใช้ความพยายามมากในการคงข้อกำหนดด้านความเป็นเอกลักษณ์ทั่วทั้งฐานข้อมูล
- ทุกตารางถูกย้ายขึ้นไปอยู่บน shard
ตุลาคม 2012: 22 ล้าน MAU, วิศวกร 40 คน
- สถาปัตยกรรมยังคงเดิม เพียงแค่เพิ่มระบบแบบเดียวกันอีกหลายเครื่อง
- Amazon EC2 + S3 + CDNs (EdgeCast, Akamai, Level 3)
- 180 web servers + 240 API engines (Flask)
- 88 MySQL DBs + 88 secondaries แต่ละตัว
- 110 Redis instances
- 200 Memcache instances
- 4 Redis Task Managers + 80 Task Processors
- Apache Solr แบบ sharded
- เริ่มย้ายจากฮาร์ดดิสก์ไปเป็น SSD
- บทเรียนสำคัญ: ทางเลือกที่จำกัดและผ่านการพิสูจน์แล้ว (limited, proven choices) นั้นดีกว่า
- การยึดใช้ EC2 และ S3 ทำให้ตัวเลือกด้านการตั้งค่ามีน้อยลง ลดเรื่องปวดหัว และเพิ่มความเรียบง่าย
- แต่ก็ทำให้อินสแตนซ์ใหม่พร้อมใช้งานได้ในไม่กี่วินาที นั่นคือเพิ่ม Memcache instance 10 ตัวได้ในเวลาเพียงไม่กี่นาที
โครงสร้างฐานข้อมูลของ Pinterest
- IDs
- คล้าย Instagram เพราะมีโครงสร้าง ID ที่ไม่ซ้ำกันจากการ sharding
- องค์ประกอบของ ID 64 บิต
- Shard ID : อยู่ shard ไหน 16 บิต
- Type : ประเภทของอ็อบเจ็กต์ (เช่น Pin) 10 บิต
- Local ID : ตำแหน่งในตาราง 38 บิต
- โครงสร้าง lookup ของ ID นี้เป็นเพียง Python dictionary แบบง่าย ๆ
- Tables
- มีทั้ง object table และ mapping table
- object table ใช้สำหรับ pin, board, comment, user ฯลฯ โดยเป็น local ID ที่แมปไปยัง MySQL Blob (JSON)
- mapping table คือ table สำหรับข้อมูลความสัมพันธ์ระหว่างอ็อบเจ็กต์ เช่น map board กับ user หรือ map like กับ pin โดยเป็น full ID ที่แมปกับ full ID และ timestamp
- ทุก query ใช้ PK (primary key) หรือ index lookup เพื่อประสิทธิภาพ และตัด join ออกทั้งหมด
1 ความคิดเห็น
วิธีที่ Instagram รองรับผู้ใช้ 14 ล้านคนด้วยวิศวกรเพียง 3 คน
เป็นบทความในซีรีส์เดียวกันกับอันนี้ และเนื้อหาก็เชื่อมโยงกันด้วย
"ทำให้เรียบง่ายเข้าไว้ ใช้เทคโนโลยีที่เป็นที่รู้จักดีและผ่านการพิสูจน์แล้ว"