Scaling Pinterest - From 0 To 10s Of Billions Of Page Views A Month In Two Years

Bài tóm tắt Pinterest 2013 2. Tăng trưởng Độ khó: Trung bình

Pinterest · 2013 · 2. Tăng trưởng · Độ khó: Trung bình — bài gốc

Theo Pinterest qua lời kể của HighScalability (Todd Hoff tóm tắt talk của Yashwanth Nelapati và Marty Weiner). Số liệu theo talk, năm ghi kèm.

Bối cảnh và các giai đoạn

  • 3/2010: 2 nhà sáng lập, 1 kỹ sư, Rackspace, 1 web engine nhỏ, 1 MySQL nhỏ.
  • 1/2011: EC2 + S3 + CloudFront, 4 web engine (để dự phòng), 1 MySQL + 1 read slave, 1 MongoDB cho counter, 2 kỹ sư.
  • Tới 9/2011, "thời thử nghiệm": tăng gấp đôi mỗi 1,5 tháng, thứ gì cũng hỏng hằng đêm. Thêm công nghệ theo các white paper: MySQL chia theo chức năng (5 DB + 9 slave), 4 node Cassandra, 15 node Membase (3 cụm), Memcache, Redis, Elasticsearch, 3 cụm Mongo, chỉ với 3 kỹ sư. Năm công nghệ DB khác nhau, mỗi cái hỏng theo cách riêng khi bị đẩy tới giới hạn.
  • 1/2012, "thời trưởng thành": sau một đợt kiến trúc lại, chỉ còn MySQL shard (66 DB + 1 slave mỗi cái), Redis, Memcache, Solr shard; 6 kỹ sư.
  • 10/2012: khoảng 4 lần so với tháng 1: 180 web engine, 240 API engine, 88 MySQL (cc2.8xlarge) + 1 slave mỗi cái, 110 Redis, 200 Memcache, 40 kỹ sư. Tăng trưởng bằng cách thêm nhiều hơn cùng một loại máy.

Lựa chọn công nghệ

  • Tiêu chí sau khi bị "đốt": trưởng thành, đơn giản, phổ biến và được ưa, hỗ trợ tốt, hiệu năng ổn định, ít kiểu hỏng, miễn phí. Giữ MySQL (chưa bao giờ sập hay mất dữ liệu, tuyển được người, latency tăng tuyến tính theo tải), Memcache, Redis, Solr; bỏ Cassandra, Mongo, Membase.
  • Redis cho home feed chỉ snapshot mỗi 3 giờ, không replication: mất máy thì mất vài giờ dữ liệu, chấp nhận để đơn giản (bình luận dưới bài phản bác rằng điều này chỉ đúng với dữ liệu không có giá trị tiền bạc).

Clustering hay sharding

  • Clustering (Cassandra, Membase, HBase: dữ liệu tự phân phối, tự di chuyển, node nói chuyện với nhau) theo kinh nghiệm của họ: còn non, phức tạp, ít người biết, nâng cấp đáng sợ, và thuật toán quản lý cụm là điểm hỏng chung: bug của nó làm sập mọi node, đã làm họ sập 4 lần. Các ca gặp: rebalance kẹt giữa chừng không có công cụ gỡ; cân bằng sai dồn dữ liệu về một node; lỗi quyền sở hữu: một secondary mới tới khoảng 80% thì tự nhận là primary, mất 20% dữ liệu mà không biết là phần nào.
  • Sharding (thủ công: dữ liệu không bao giờ di chuyển, node không biết nhau): thắng vì thuật toán đặt dữ liệu chỉ nửa trang code. Đổi lại mất join, mất giao dịch xuyên DB, ràng buộc chuyển lên ứng dụng, báo cáo phải chạy trên mọi shard.

Cách shard

  • Bảng Pin tới 1 tỉ dòng thì index hết RAM. Tách bảng lớn nhất ra DB riêng, rồi hết chỗ, rồi phải shard. Lộ trình: 1 DB + khoá ngoại + join → denormalize + cache → read slave + cache (slave lag làm bản ghi như biến mất, phải che bằng cache) → chia theo chức năng → shard theo ID.
  • Preshard theo dự báo 5 năm: 8 máy vật lý × 512 DB, mọi DB có mọi bảng. Mỗi master chạy multi-master với một bản ở AZ khác. Khi một DB nặng lên: dựng slave, đổi ánh xạ trong code, vài phút ghi vẫn vào node cũ và được replicate, rồi cắt.
  • ID 64 bit = shard ID 16 bit + type 10 bit + local ID (auto increment của MySQL). Không dùng bảng tra ánh xạ như Twitter vì mỗi query MySQL trên AWS khoảng 3 ms. Mọi dữ liệu của một user (board, pin) nằm cùng shard với user nên trang profile không cần query xuyên shard. Mở 4.096 trong 65.536 shard ID; user mới phân ngẫu nhiên.
  • Object là blob JSON (đang chuyển sang Thrift) theo local ID, có version, nâng cấp khi đọc nên không cần ALTER TABLE; quan hệ là bảng mapping (user_has_boards), index mới là bảng mới. Bảng user (kiểm trùng tên và email) không shard.
  • Chuyển dữ liệu: feature freeze; ghi cả hệ cũ lẫn mới; "scripting farm" dựng trên Pyres (Resque trên Redis, sau thay luôn Celery và RabbitMQ) chuyển 500 triệu pin và 1,6 tỉ dòng follower; dự kiến 2 tháng, thật là 4–5 tháng, phải chạy lại nhiều lần vì user báo thiếu board.
  • Hướng tiếp: 30.000 kết nối vào Memcache làm daemon swap; chuyển sang service (ví dụ follower service) để chỉ khoảng 30 máy chạm DB và cache.

Bài học cho SWE

  • Theo Pinterest, kiến trúc đúng là khi tăng trưởng giải bằng cách thêm nhiều hơn cùng một thứ (Sharding và tách database).
  • Càng ít di chuyển dữ liệu giữa node càng ổn định; thuật toán đặt dữ liệu đơn giản dễ kiểm chứng hơn cluster manager thông minh (Chọn database theo workload).
  • Nhúng vị trí vào ID bỏ được một bước tra cứu, nhưng khoá dữ liệu vào shard mãi mãi (Sinh ID phân tán).
  • Migration dữ liệu luôn lâu hơn dự tính; ghi kép và chạy lại script cho tới khi đủ (Migration không downtime).

Liên quan