Analysis of recent downtime & what we're doing to prevent future incidents
Bài tóm tắt Asana 2019 3. Quy mô lớn Độ khó: Trung bình
Asana · 2019 · 3. Quy mô lớn · Độ khó: Trung bình — bài gốc
Bối cảnh
- Đa số dữ liệu người dùng của Asana đã shard, nhưng một phần mô hình dữ liệu dùng chung cho mọi team/workspace của user nằm trong một database dùng chung (MySQL trên RDS, cấu hình HA).
- Ba lần downtime vì database này: ít nhất 92 phút (29/7/2019), 51 phút (1/8), 34 phút (13/8). Kỳ vọng thường lệ: phần cứng hỏng thì failover sang hot spare mất vài phút, ứng dụng retry.
- Có cơ chế chống phản hồi dương/sụp dây chuyền do quá tải ở nơi khác, nhưng không đặt tương tự cho DB này, một phần vì kích nhầm cũng gây mất tính năng lõi.
Thay đổi chính
- Sự cố 1: latency ở hệ khác sinh request trùng chồng nhau → bug ứng dụng + vòng phản hồi dương: khi kết nối bão hoà, ghi timeout; giới hạn tốc độ ghi dựa trên giá trị lần cuối vốn không được cập nhật, nên càng timeout càng ghi nhiều. Failover lần đầu không xong bình thường, phải ngắt mọi client; failover lần hai với mọi server tắt rồi bật dần. Vì DB quá tải nên thiếu dữ liệu giám sát, đội kết luận sai rằng hiệu năng kém do quy trình failover.
- Sự cố 2: lỗi volume EBS gây latency khoảng 1 phút → đồng thời tăng vọt, timeout, tràn hàng đợi; failover thành công nhưng DB mới cũng quá tải. Phục hồi nhờ chặn một endpoint nội bộ. Lúc này mới thấy tranh chấp là hệ quả của quá tải chứ không phải nguyên nhân; vài thay đổi sau sự cố 1 còn làm đợt tải đầu dốc hơn (đã gỡ).
- Sự cố 3: lại lỗi EBS (khoảng 30 giây); failover hai lần, lần hai kèm load shedding nội bộ; phục hồi nhanh hơn nhưng vẫn chưa đủ.
- Sửa ngắn hạn: chặn vòng phản hồi bằng Redis làm khoá/cache tạm (check-and-set: đã thử cập nhật trong N giây gần đây thì không thử nữa, nên tốc độ thử ghi không đổi dù chậm hay lỗi); back-off khi upstream quá tải (chờ rồi trả lỗi để client retry có trễ); admission control ở tầng storage (
innodb_thread_concurrency) và tầng ứng dụng (sức khoẻ theo latency và số kết nối đang hoạt động); load test tới khi hỏng để tái hiện và xác nhận hệ phục hồi được. - Dài hạn: chuyển dữ liệu kiểu này khỏi RDS dùng chung sang kho ít điểm hỏng đơn hơn (như DynamoDB, chấp nhận đổi ngữ nghĩa dữ liệu), cải thiện giám sát (tích hợp OpenTracing), giảm phụ thuộc vào DB dùng chung khi tách monolith thành service.
Vì sao
- Failover chỉ thay máy; nếu tải vượt sức thì máy mới cũng ngập. Thiếu admission control, hệ không tự về trạng thái tốt dù nguyên nhân ban đầu đã hết.
Bài học cho SWE
- Phản hồi dương (latency → thêm việc → thêm latency) giữ hệ ở trạng thái hỏng sau khi tác nhân đã qua.
- Khi hệ quá tải, giám sát cũng thiếu dữ liệu; dễ kết luận nhầm nguyên nhân và kết quả.
- Dữ liệu dùng chung chưa shard là điểm hỏng đơn ngay cả khi phần còn lại đã shard.
Liên quan
- Sự cố và postmortem · Load shedding, rate limit và backpressure
- Chủ động cắt kết nối ở proxy DB khi pool cạn: Airbnb 2016
#postmortem#shared database#RDS MySQL Multi-AZ#failover#positive feedback loop#admission control#innodb_thread_concurrency#load shedding#EBS#load test to failure
Được nhắc tới trong
Công ty (1)
Bài tóm tắt (1)