Modernizing Artifact Storage at Uber

Bài tóm tắt Uber 2026 4. Điều chỉnh Độ khó: Trung bình

Uber · 2026 · 4. Điều chỉnh · Độ khó: Trung bình — bài gốc

Bối cảnh

  • Mọi build ở Uber (monorepo Go, Java, web, Android, iOS, Python và hàng nghìn microrepo) phụ thuộc hàng trăm tới hàng nghìn artifact. Hơn mười năm, một nền tảng artifact của bên thứ ba tự host ở hai data center nằm trên đường găng của build: GeoDNS đưa client tới DC gần nhất; thiếu artifact thì hỏi DC kia rồi lưu lại; nhân bản đẩy bất đồng bộ khi ghi, cộng cron vét những gì sót; DC hỏng thì GeoDNS chuyển traffic.
  • Vấn đề khi lớn lên: đĩa mỗi node có hạn, đầy là không ghi được hoặc không đạt replication factor (đọc chậm vì I/O), phải rebalance tay mất hàng giờ tới hàng ngày, có lúc làm hệ gần như không dùng được, có rủi ro mất dữ liệu; nhân bản lỗi âm thầm nên artifact có thể chỉ nằm trên một node (cron phát hiện và báo); đĩa gắn liền nên hỏng phần cứng là phải sơ tán hàng trăm TB bằng script, có lúc không sơ tán được; nâng cấp phần mềm cần migration schema nhiều TB và nhiều bước tay, có thể mất cả cụm.

Thay đổi chính

  • Chuyển sang dịch vụ SaaS quản lý sẵn: nhiều region cloud, nhân bản bất đồng bộ giữa region, artifact nằm trên blob store của cloud (không còn giới hạn đĩa, hỏng node ít rủi ro), nhà cung cấp lo nâng cấp và vá bảo mật.
  • Cái giá mới là phí egress: Uber tải hơn 5 PB artifact mỗi tháng, và tăng theo số build.
  • Proxy kiểm tra (validation proxy), không phải cache theo TTL: mọi request vẫn được chuyển tới SaaS; nếu proxy đã thấy artifact thì gửi kèm If-None-Match / If-Modified-Since. 304 Not Modified thì phục vụ byte từ cache nội bộ; 200 OK thì stream thẳng cho client và cập nhật cache bất đồng bộ. Metadata (URL, checksum, last-modified) trong MySQL. Đã cân nhắc proxy HTTP chung như NGINX nhưng ngữ nghĩa TTL và xoá best-effort không hợp yêu cầu đúng đắn của artifact (kiểm mỗi request, nhất quán mạnh, chuyển thẳng khi lỗi).
  • Kết quả, theo Uber: egress từ SaaS giảm hơn 99%, chi phí egress liên quan artifact giảm gần 90%, chi phí tăng chủ yếu theo artifact mới chứ không theo lượt tải lặp lại; độ tin cậy 99,99% đo ở proxy; latency tương đương on-prem cũ (lượt kiểm chỉ là metadata); thấy được mọi request, hành vi cache, và độ trễ nhân bản giữa region của SaaS.
  • Chế độ hỏng, đều về phía tốn hơn chứ không sai: cache hay MySQL hỏng thì chuyển tay sang passthrough; proxy active-active nhiều node, nhiều DC; DC hoặc region SaaS sập thì GeoDNS chuyển; không bao giờ phục vụ mà không kiểm với origin; tải dở dang bị bỏ trước khi vào cache.
  • Bài học từ production: công cụ build và retry dùng nhiều Range request, không cache 206 thì tải lại cả artifact lớn; một phần rất nhỏ artifact trên 8 GB chiếm tỉ lệ egress lớn; cần cache cục bộ trên node cho đợt bùng; có dấu hiệu thundering herd quanh artifact nóng lúc đỉnh build, đang làm request coalescing và backpressure.

Vì sao

  • Tự host kho có trạng thái trên đĩa gắn liền làm mọi sự cố đĩa, node, nâng cấp thành việc tay rủi ro cao; dịch vụ quản lý bỏ rủi ro đó nhưng đổi sang chi phí theo byte tải, nên cần một lớp chặn lượt tải lặp mà không đánh mất nguồn sự thật.

Bài học cho SWE

  • Chuyển từ tự host sang dịch vụ cloud đổi chi phí vận hành thành chi phí theo lưu lượng; tính egress trước.
  • Khi đúng đắn quan trọng hơn latency, dùng cache kiểu xác thực lại (conditional request) thay vì TTL: rẻ vì chỉ kiểm metadata, đúng vì origin luôn quyết.
  • Thiết kế để mọi lỗi của lớp tối ưu suy giảm về "đắt hơn, chậm hơn" chứ không về "sai".
  • Đo theo mẫu truy cập thật (Range, file rất lớn, artifact nóng) sau khi lên production.

Liên quan