Nén Metadata Video Với Protobuf
Worker nạp dữ liệu (ingest worker) của chúng tôi thu thập hàng nghìn video đang thịnh hành sau mỗi hai giờ. Chúng tôi gửi dữ liệu này đến ba dịch vụ: một dịch vụ xếp hạng (ranking service), một dịch vụ làm nóng bộ nhớ đệm (cache warmer) và một tác vụ phân tích (analytics job).
Trong một thời gian dài, chúng tôi đã sử dụng JSON để truyền dữ liệu này. Nó hoạt động tốt cho đến khi gặp sự cố.
Một bản ghi video duy nhất chiếm 2,4 KB trong định dạng JSON. Việc chuyển 40.000 bản ghi đến ba dịch vụ khác nhau đồng nghĩa với việc phải truyền 280 MB văn bản dư thừa sau mỗi hai giờ. Điều này gây lãng phí băng thông và làm chậm các worker PHP của chúng tôi.
Chúng tôi đã chuyển sang Protocol Buffers (Protobuf). Dưới đây là lý do tại sao và cách nó đã thay đổi hệ thống của chúng tôi.
Ba vấn đề chính với JSON:
- Kích thước: JSON lặp lại tên trường (field name) trong mỗi bản ghi. Một tên trường như "viral_score_24h" tiêu tốn tới 15 byte chỉ để mang một con số 8 byte.
- Chi phí phân tích (Parse Cost): PHP phải phân tích toàn bộ khối JSON ngay cả khi một dịch vụ chỉ cần hai trường.
- Sai lệch lược đồ (Schema Drift): JSON không có hợp đồng (contract). Nếu một dịch vụ thay đổi một trường, các dịch vụ khác sẽ bị lỗi âm thầm trong quá trình chạy (runtime).
Cách Protobuf giải quyết vấn đề này:
Protobuf sử dụng số thứ tự trường thay vì tên. Nó sử dụng một tệp .proto làm nguồn sự thật duy nhất (single source of truth). Tệp này sẽ tạo mã cho PHP, Python và Go. Nếu bạn thay đổi lược đồ (schema), mã sẽ không thể biên dịch được. Điều này giúp chuyển các lỗi runtime thành lỗi compile-time.
Kết quả:
Chúng tôi đã đo lường những thay đổi này trong vòng một tuần:
- Kích thước payload: Giảm từ 2,4 KB xuống còn 720 bytes (giảm 70%).
- Thời gian Encode PHP: Giảm từ 310 ms xuống 95 ms.
- Thời gian Decode Go: Giảm từ 140 ms xuống 38 ms.
- Băng thông: Giảm từ 280 MB xuống còn 84 MB mỗi chu kỳ.
Khi nào nên sử dụng Protobuf:
Đừng sử dụng nó cho mọi thứ. Nếu payload của bạn nhỏ hoặc bạn cần con người có thể đọc chúng một cách dễ dàng, hãy tiếp tục dùng JSON. Hãy sử dụng Protobuf cho lưu lượng truy cập nội bộ khối lượng lớn, nơi tốc độ và các hợp đồng nghiêm ngặt là quan trọng nhất.
Các API công khai của chúng tôi vẫn sử dụng JSON. Các dịch vụ nội bộ của chúng tôi sử dụng Protobuf.