The growing pains of database architecture
Bài tóm tắt Figma 2023 2. Tăng trưởng Độ khó: Trung bình
Figma · 2023 · 2. Tăng trưởng · Độ khó: Trung bình — bài gốc
Bối cảnh
- 2020: thêm tính năng, chuẩn bị ra sản phẩm thứ hai, user tăng. Traffic DB tăng khoảng 3 lần mỗi năm.
- Phần lớn metadata (quyền, thông tin file, comment) nằm trên một Amazon RDS Postgres. Giờ cao điểm CPU vượt 65%, latency ngày càng khó đoán. Theo Figma: nếu DB bão hoà hoàn toàn thì Figma ngừng hoạt động. Lúc đó còn xa ngưỡng đó, nhưng họ muốn xử lý trước.
Thay đổi chính
1. Mua thêm ~1 năm "đường băng":
- Lên máy lớn nhất (r5.12xlarge → r5.24xlarge).
- Thêm read replica.
- DB mới cho tính năng mới.
- PgBouncer khi số kết nối lên hàng nghìn.
Giới hạn của các biện pháp này: lượt ghi chiếm phần lớn tải, và nhiều lượt đọc không chuyển sang replica được vì app nhạy với replication lag.
2. Loại shard ngang (lúc đó):
- Giải pháp managed scale ngang phần lớn không tương thích Postgres.
- NoSQL hoặc Vitess (MySQL) đòi migration đọc/ghi kép phức tạp, NoSQL còn phải sửa app nhiều.
- NewSQL tương thích Postgres: Figma sẽ thành một trong những cluster lớn nhất, không muốn là khách đầu tiên gặp lỗi scale.
- Tự host thì đội chưa có kỹ năng.
3. Chọn tách dọc theo nhóm bảng:
- Chọn bảng theo hai tiêu chí:
- Tác động: đo average active sessions bằng cách lấy mẫu
pg_stat_activitymỗi 10ms, gộp theo bảng. - Mức cô lập: tách bảng sẽ mất transaction, foreign key, JOIN. Vì Ruby/ActiveRecord quá động để phân tích tĩnh, họ gắn validator lúc chạy vào ActiveRecord, gửi thông tin query/transaction về data warehouse rồi tìm nhóm bảng hay đi cùng nhau.
- Tác động: đo average active sessions bằng cách lấy mẫu
- Mục tiêu migration: ảnh hưởng availability dưới 1 phút, tự động hoá để lặp lại được, hoàn tác được. Không có sẵn công cụ đáp ứng nên tự xây.
- Hai pha:
- Tách PgBouncer trước. Mỗi nhóm bảng có PgBouncer riêng nhưng vẫn trỏ về DB cũ; security group buộc mọi client đi qua PgBouncer. Route sai thì phát hiện được mà chưa hỏng gì.
- Rồi mới tách dữ liệu.
- Logical replication (không dùng streaming), vì nó:
- chỉ chép một tập bảng;
- chép được sang bản Postgres major khác, nên dùng luôn để nâng cấp;
- cho phép replication ngược để rollback.
- Chép ban đầu nhanh hơn: bản đầu tiên rất chậm vì index ở DB đích được cập nhật từng hàng. Họ xoá index ở DB đích rồi dựng lại sau, thời gian chép giảm từ vài ngày/tuần xuống vài giờ.
- Cutover: PgBouncer tạm dừng kết nối mới → thu quyền query trên bảng ở DB cũ → huỷ query còn chạy (thường dưới 10) → lấy LSN ở DB cũ và chờ DB mới replay qua LSN đó → promote → bật replication ngược → cho traffic chạy lại sang DB mới.
Kết quả
- Đã chạy nhiều lần trên production: lần đầu 2 bảng nhiều traffic, lần cuối (10/2022) 50 bảng.
- Mỗi lần có khoảng 30 giây ảnh hưởng một phần (~2% request bị rớt).
- Partition lớn nhất chỉ còn ~10% CPU.
Vì sao
Theo Figma: giảm rủi ro bất ổn mà không hy sinh độ tin cậy ("không thể đóng cao tốc trong lúc sửa").
Bài học cho SWE
- Đo theo bảng (AAS) để biết tách gì có tác động nhất.
- Chèn một lớp proxy rồi tách nó trước dữ liệu, nhờ vậy lỗi routing lộ ra khi vẫn còn an toàn.
- Thiết kế rollback từ đầu (replication ngược).
- Hiểu nguyên nhân chậm (index cập nhật từng hàng) thay vì chấp nhận nó.
- Giới hạn tự nhận: số DB tăng làm routing ở client phức tạp, nên họ thêm query routing service. Bảng tỷ hàng vẫn sẽ chạm trần, dẫn tới shard ngang: Figma 2024.
Liên quan
Được nhắc tới trong
Chủ đề (4)
Công ty (1)
Bài tóm tắt (5)