Keeping Counts In Sync
Bài tóm tắt SoundCloud 2018 3. Quy mô lớn Độ khó: Trung bình
SoundCloud · 2018 · 3. Quy mô lớn · Độ khó: Trung bình — bài gốc
Bối cảnh
- Số lượt nghe, like, repost của mỗi track: vừa là thống kê cho creator (tổng theo khoảng thời gian bất kỳ, xem chi tiết theo ngày/giờ và phải cộng khớp), vừa là bộ đếm công khai hiện ở mọi nơi track xuất hiện, được đọc nhiều hơn thống kê vài bậc độ lớn.
- Bài tiếp nối bài trước về hệ đếm realtime Stitch.
Kiến trúc hiện tại (2018)
- Lambda Architecture dạng tăng dần: không tính lại tầng serving từ đầu, chỉ tính lại các bucket giờ/ngày/tháng thay đổi (job ngày và job tháng trên Hadoop/Crunch, đọc dữ liệu từ pipeline event dựa trên Kafka). Dựa trên nhận xét lượt nghe hầu như không đến từ quá khứ (trừ spam và backfill do bug).
- Cả tầng batch và tầng realtime dùng Cassandra: batch nạp bằng SSTable loading; realtime dùng distributed counter của Cassandra, mỗi event là một lệnh tăng/giảm. API Stitch "khâu" hai tầng thành một kết quả.
- Tổng đếm: muốn tổng mọi thời gian phải đọc mọi bucket, nên thêm Memcached phục vụ khoảng 90% bộ đếm được hỏi nhiều nhất. Tăng cả Cassandra và cache cùng lúc; vì pipeline chỉ at-least-once và cập nhật không giao dịch, hai bên lệch dần, nên vô hiệu toàn bộ cache mỗi ngày với TTL ngẫu nhiên để các track nóng không hết hạn cùng lúc gây đỉnh tải.
- Top list ở một hệ riêng cùng đọc pipeline; khó là giữ hai hệ chạy cùng nhịp và tính lại đồng bộ khi có sự cố, lọc spam ở phía upstream chung.
Các phương án đã thử (chưa đổi)
- Đếm thẳng mọi lúc (từ thời đầu: một database lớn chứa mọi event): không khả thi; database phân tích cột (Redshift, BigQuery, Kudu, Vertica) trả lời trong giây chứ không phải mili giây.
- Tiền tổng hợp kiểu khác (cây Fenwick, prefix sum, dịch vụ có trạng thái đọc partition Kafka): latency kém hơn Cassandra và code phức tạp hơn nhiều, "gần như viết lại một database".
- Chỉ tổng hợp phần được hỏi (cache thích ứng).
- Theo SoundCloud: chưa phương án nào đủ đột phá để bù chi phí vận hành và latency tăng thêm.
Bài học cho SWE
- Cache cho bộ đếm cập nhật kép không giao dịch sẽ trôi; xoá định kỳ là cách chặn độ trôi đơn giản nhất (Cache và invalidation).
- TTL phải ngẫu nhiên để các khoá nóng không hết hạn cùng lúc (Hot partition và thundering herd).
- Tiền tổng hợp đổi dung lượng lấy latency mili giây; xem lại định kỳ các phương án khác là cách kiểm chứng lựa chọn cũ còn đúng (Chọn database theo workload).
Liên quan
Được nhắc tới trong
Công ty (1)
Bài tóm tắt (1)