A Brief History of Scaling LinkedIn

Bài tóm tắt LinkedIn 2015 4. Điều chỉnh Độ khó: Dễ

LinkedIn · 2015 · 4. Điều chỉnh · Độ khó: Dễ — bài gốc

Bài khung của trang LinkedIn: tóm tắt 12 năm kiến trúc, mỗi mục trỏ sang bài chi tiết. Đọc bài này trước các bài LinkedIn khác.

Bối cảnh

  • LinkedIn ra đời năm 2003, tuần đầu có 2.700 thành viên. Năm 2015: hơn 350 triệu thành viên, hàng chục nghìn page mỗi giây, mobile chiếm hơn 50% traffic, backend chịu hàng triệu query mỗi giây.

Thay đổi chính

  • Leo: ban đầu là một monolith (servlet cho mọi trang, business logic, kết nối vài database).
  • Service đầu tiên là member graph ("Cloud"): đồ thị kết nối cần duyệt trong bộ nhớ, có profile tải khác hẳn Leo nên tách ra scale riêng, gọi qua Java RPC. Search (Lucene) là service thứ hai, nhận dữ liệu từ graph.
  • Replica đọc: DB profile bị Leo dồn tải. Đầu tiên scale dọc (thêm CPU, RAM), sau đó thêm replica chỉ đọc, đồng bộ bằng phiên bản đầu của Databus, kèm logic biết khi nào đọc replica là an toàn. Bài ghi chú rằng mô hình master/slave chỉ là giải pháp trung hạn; về sau chuyển sang DB phân vùng.
  • "Kill Leo": Leo hay sập, khó debug và khó release, nên khẩu hiệu "Kill Leo" kéo dài nhiều năm. Tách dần API và logic (search, profile, communications, groups) rồi tới tầng giao diện; sản phẩm mới viết ngoài Leo. Thành các stack dọc theo chức năng: frontend dựng HTML, mid-tier cung cấp API cho model, backend truy cập DB. 150 service năm 2010, hơn 750 năm 2015. Service stateless nên scale bằng thêm instance sau load balancer phần cứng; mỗi service được redline để biết giới hạn tải.
  • Cache: thêm memcache/Couchbase ở mid-tier và Voldemort chứa kết quả tính sẵn. Sau đó gỡ bớt cache mid-tier: chúng giữ dữ liệu dẫn xuất từ nhiều domain nên invalidation và call graph vượt tầm kiểm soát. Theo LinkedIn, cache nên đặt sát kho dữ liệu nhất có thể.
  • Kafka: nhiều pipeline riêng (vào data warehouse, vào Hadoop, log, tracking, queue cho InMail, cập nhật search khi đổi profile) phải scale từng cái; Kafka thay tất cả bằng một pipeline quanh commit log (hơn 500 tỷ event/ngày năm 2015).
  • Inversion (cuối 2011): dừng phát triển tính năng để cả tổ chức engineering tập trung vào tooling, deploy, hạ tầng và năng suất.
  • Rest.li: API thời SOA giả định Java RPC, không đồng nhất giữa team và dính chặt tầng giao diện. Rest.li là API REST theo data model, JSON qua HTTP, cho phép client không phải Java; D2 (Dynamic Discovery) làm load balancing phía client và service discovery. Năm 2015 có hơn 975 resource, hơn 100 tỷ call Rest.li/ngày.
  • Super block: fan-out lớn (trang profile gọi hàng trăm service phía dưới) được gom thành nhóm service backend có một API truy cập duy nhất, do một team tối ưu.
  • Multi-data center: đầu tiên phục vụ public profile từ hai data center (Los Angeles, Chicago), rồi mọi service phải xử lý replication, callback từ nhiều nguồn và ghim người dùng vào data center gần. Espresso hỗ trợ master/master. Năm 2015: ba data center chính và các PoP.
  • Còn lại: Samza, Espresso, Voldemort, Pinot; workflow offline Hadoop + Voldemort tính sẵn People You May Know; client template, BigPipe, Play (non-blocking); nhiều lớp proxy Apache Traffic Server và HAProxy.

Vì sao

  • Mỗi bước sinh ra từ nút thắt cụ thể: profile DB quá tải → replica; Leo khó release → SOA; pipeline nhân bản → Kafka; API không đồng nhất → Rest.li; fan-out mất kiểm soát → super block; một data center là single point of failure → multi-DC.

Bài học cho SWE

  • Service đầu tiên nên tách là phần có profile tải khác hẳn monolith (graph trong bộ nhớ), không phải phần dễ tách nhất.
  • Cache ở tầng giữa giữ dữ liệu ghép từ nhiều domain là nợ invalidation; LinkedIn đã phải gỡ chúng.
  • Microservice tự đẻ ra bài toán fan-out; cần một cấu trúc gom lại (super block) chứ không chỉ chia nhỏ thêm.
  • Có lúc phải dừng tính năng để trả nợ hạ tầng (Inversion).

Liên quan