The Architecture Twitter Uses to Deal with 150M Active Users, 300K QPS, a 22 MB/S Firehose, and Send Tweets in Under 5 Seconds

Bài tóm tắt Twitter 2013 3. Quy mô lớn Độ khó: Trung bình

Twitter · 2013 · 3. Quy mô lớn · Độ khó: Trung bình — bài gốc

Nguồn thứ cấp: Todd Hoff (HighScalability) tóm tắt talk của Raffi Krikorian. Nhận định ghi "theo Twitter qua lời kể của HighScalability". Bài ngoài sheet, lấy để trả lời câu hỏi mở về fan-out timeline của Twitter.

Bối cảnh (2013)

  • 150 triệu user hoạt động; 300K QPS đọc timeline nhưng chỉ khoảng 6.000 request/giây ghi: Twitter chủ yếu là nơi tiêu thụ. 400 triệu tweet/ngày (trung bình 5K/giây, đỉnh 7K/giây, hơn 12K/giây khi có sự kiện lớn); firehose 22 MB/giây.
  • Từ một site Rails ba tầng thành lõi các service (Timeline, Tweet, User, Social Graph); team platform cam kết để team sản phẩm khỏi lo về scale.
  • Tính home timeline lúc đọc bằng một câu select khổng lồ trên toàn bộ Twitter "đã thử và đã chết".

Thay đổi chính

  • Fan-out lúc ghi cho home timeline: tweet tới thì áp luật nghiệp vụ ngay, hỏi Flock (đồ thị follow) rồi chèn ID tweet vào list của từng follower trong cụm Redis (vài TB RAM, mỗi timeline nhân 3 bản trên 3 máy, pipeline 4.000 đích mỗi lần). Mỗi phần tử chỉ là ID tweet, ID người gửi và vài bit cờ. Timeline giới hạn 800 phần tử; chỉ user hoạt động trong 30 ngày mới có timeline trong RAM, người khác phải "dựng lại" từ đồ thị và đĩa (MySQL qua Gizzard) khi quay lại.
  • Đọc: O(1) tìm máy giữ timeline, lấy bản nào nhanh nhất trong 3; rồi "hydrate" ID thành nội dung bằng multiget song song từ các service có cache riêng (cache user chứa toàn bộ user base, cache tweet giữ khoảng 1,5 tháng gần nhất). Khoảng 400 ms qua API.
  • Search làm ngược lại: ghi O(1) vào một máy Early Bird (Lucene sửa, index trong RAM), đọc O(n) bằng scatter-gather qua mọi shard rồi xếp hạng lại (Blender), khoảng 100 ms.
  • Tách đồng bộ: trước đây ghi tweet là đồng bộ; khoảng 2011 chuyển sang nhận tweet (tới 145 ms) rồi giao phần còn lại cho đường bất đồng bộ, một phần vì đường ghi chạy Ruby đơn luồng.

Vấn đề và hướng đi (theo Twitter qua HighScalability)

  • Tài khoản nhiều follower: một tweet của người có hàng chục triệu follower là hàng chục triệu lần chèn; giao hàng p50 tới 1 triệu người mất 3,5 giây, p99 tới 5 phút. Hệ quả: reply tới trước tweet gốc, người follow sau thấy tweet trước người follow lâu, race condition khắp site, càng tệ khi người nổi tiếng nói chuyện với nhau.
  • Hướng đi: không fan-out cho các tài khoản rất lớn nữa, mà trộn timeline của họ vào lúc đọc; cân lại đường đọc và ghi, theo Twitter tiết kiệm được "vài chục phần trăm" tài nguyên tính toán.
  • Giám sát: dashboard VIZ cho mọi cụm (Timeline Service p50 5 ms, p99 100 ms, p99.9 chạm đĩa vài trăm ms), Zipkin để trace request qua mọi service.

Bài học cho SWE

  • Chọn tính trước lúc ghi hay tính lúc đọc theo tỉ lệ đọc/ghi; với tỉ lệ 50:1, đẩy việc sang lúc ghi là hợp lý.
  • Phân phối số follower lệch làm fan-out-on-write có đuôi rất dài; lời giải thực tế là lai: fan-out cho đa số, kéo lúc đọc cho phần đuôi.
  • Giới hạn kích thước (800 phần tử, chỉ user hoạt động) là cách giữ chi phí RAM có trần.

Liên quan