Upscaling LinkedIn's Profile Datastore While Reducing Costs
Bài tóm tắt LinkedIn 2023 4. Điều chỉnh Độ khó: Khó
LinkedIn · 2023 · 4. Điều chỉnh · Độ khó: Khó — bài gốc
Bối cảnh
- Đỉnh 4,8 triệu profile/giây, request tới storage gấp đôi mỗi năm (2023). Profile hơn 99% là đọc.
- Lịch sử: memcached làm cache đọc trước DB, khó vận hành (suy giảm khi mở rộng, thay node, cache lạnh). Chuyển từ Oracle sang Espresso năm 2014 thì bỏ cache; Espresso profile được mở rộng tới hơn 1,4 triệu QPS bằng cách thêm node, rồi chạm trần của các thành phần dùng chung trong Espresso.
- Luồng: Profile frontend → Profile backend → Espresso router (có off-heap cache OHC Window Tiny-LFU) → storage node (MySQL). Profile lưu dạng Avro binary; schema tiến hoá. OHC có hit rate thấp vì cục bộ từng router và vì request dùng projection.
Thay đổi chính
- Couchbase làm tầng cache trong storage, không fallback về nguồn sự thật: đây là cache để scale nên không được phép dội tải về Espresso khi lỗi. Ba nguyên tắc: chịu được mọi lỗi Couchbase, dữ liệu cache luôn có, SLO rõ cho độ lệch.
- Chịu lỗi: router theo dõi sức khoẻ từng bucket theo tỉ lệ lỗi, bucket xấu thì ngừng gửi (tránh dồn request trong heap); 3 replica, đọc leader rồi follower; retry lỗi do router hay mạng trên router khác.
- Luôn có dữ liệu: cache toàn bộ profile ở mọi DC (p95 dưới 24 KB) để chịu được failover DC. TTL hữu hạn để dọn bản ghi lệch (ví dụ lệnh xoá bị mất khi Kafka sự cố), cộng bootstrap định kỳ trong chu kỳ ngắn hơn TTL.
- Chống lệch: ba bên cùng ghi cache (router, cache updater, bootstrapper). Thứ tự bằng SCN (số commit logic trong binlog của Espresso): last-writer-wins theo SCN lớn nhất; xoá = upsert tombstone chỉ chứa SCN; ghi đồng thời bắt bằng Couchbase CAS và thử lại.
- Đường ghi: cache updater và bootstrapper là job Samza đọc stream CDC và stream bootstrap của Brooklin. Nhất quán cuối cùng.
- Hợp đồng cache theo request: header "staleness bound" để ứng dụng bật/tắt cache và chọn độ cũ chấp nhận được; router quyết định phục vụ từ OHC, Couchbase hay storage node.
- Cache nguyên document: projection quá đa dạng để cache theo từng kiểu, nên cache full profile; projection và nâng cấp schema chuyển về Profile backend (đọc với accept-type phiên bản 0 = như lúc ghi, backend lấy schema mới từ registry lúc chạy để chịu được canary ghi schema mới). Datum reader mới đọc thẳng Avro sang DataMap của Pegasus, nhanh hơn 28–40%.
Kết quả (2023)
- Hit rate khoảng 99%; multi-get p99 từ 31,6 ms xuống 12,41 ms (−60,7%), p99.9 −63,7%.
- Số storage node Espresso giảm 90%; trừ chi phí hạ tầng mới và CPU backend (+tối đa 30%), tiết kiệm khoảng 10% chi phí phục vụ profile mỗi năm.
Bài học cho SWE
- Cache dùng để scale khác cache dùng để tăng tốc: nếu nguồn sự thật không chịu nổi tải khi cache sập thì cache phải có HA, đầy đủ dữ liệu và không được fallback.
- Nhiều bên cùng ghi cache cần một đồng hồ logic từ nguồn (SCN, LSN) để so thứ tự, và tombstone thay cho xoá cứng.
- TTL hữu hạn + bootstrap định kỳ là lưới an toàn cho mọi sự kiện CDC bị mất.
Liên quan
#Profile#Espresso#Couchbase#Cache without fallback#SCN#Last-writer-wins#Tombstone#CAS#Brooklin CDC#Samza#Periodic bootstrap#Staleness bound header#Avro schema upconversion
Được nhắc tới trong
Công ty (1)