How We Replaced Our Data Pipeline With Zero Downtime
Bài tóm tắt Twilio 2014 2. Tăng trưởng Độ khó: Trung bình
Twilio · 2014 · 2. Tăng trưởng · Độ khó: Trung bình — bài gốc
Bối cảnh
- Mỗi cuộc gọi hay tin nhắn đi qua các trạng thái in-flight (đổ chuông, đang gọi, xếp hàng), rồi thành bản ghi post-flight để lưu lâu dài và phân tích. Trước đây cả hai nằm chung một cụm MySQL.
- Ba vấn đề:
- Tối ưu cho mọi thứ là không tối ưu cho gì: in-flight cần ghi nhiều, post-flight cần đọc nhiều mà không sửa;
- DB dùng chung bị nhiều client truy cập trực tiếp: thành điểm hỏng chung, khó biết lỗi của ai, mọi client gắn chặt vào công nghệ lưu trữ;
- giới hạn scale dọc: dữ liệu gần chạm giới hạn một node; replication đơn luồng của slave bị trễ quá ngưỡng nhất quán.
Thay đổi chính
- Đặt service trước DB để chỉ một service biết cách lưu và shard.
- Tách in-flight và post-flight ra hai kho.
- Chống "nhân tiện sửa luôn": họ cân nhắc đổi công nghệ DB (MySQL thiếu shard và HA sẵn có) nhưng giữ MySQL để giới hạn phạm vi.
- Khoá shard: AccountSid, vì hầu hết query nằm trong một account. Ánh xạ kết hợp range + lookup: range để cấu hình gọn, lookup để tách riêng một account rất lớn.
- Rollout trong vài tháng, không downtime (với công ty viễn thông, downtime là rớt cuộc gọi):
- Shadow (công cụ tự viết, mã nguồn mở): proxy gửi cùng request tới bản ổn định và bản mới, báo khác biệt, chỉ trả kết quả bản ổn định. Họ chạy shadow topology mới khoảng một tháng.
- Account Flags: bit trong DB quyết định request đi đường code nào, để bật dần theo khách.
- Đặt service abstraction (in-flight, post-flight, aggregator) giữa client (API, Web, Billing) và DB.
- Tách DB in-flight: chỉ cần trỏ service sang DB mới.
- Shard DB post-flight:
- định tuyến đọc và ghi riêng, để không có lúc một luồng ghi shard mới trong khi luồng khác còn đọc shard cũ;
- shard mới làm slave của cụm cũ, nên có đủ dữ liệu ngay khi chuyển;
- chuyển đọc trước, ghi sau;
- tránh trùng
AUTO_INCREMENTkhi cả hai master cùng nhận ghi: shard0 sinh số lẻ, shard1 số chẵn (auto_increment_offset/increment), rồi cắt replication; - xoá phần dữ liệu không còn thuộc shard và rebuild bảng để thu hồi dung lượng.
Bài học (theo Twilio)
- Hiệu ứng cánh bướm: quyết định thiết kế sớm có hậu quả lâu dài; hãy hỏi ở 10x, 100x thì sao.
- SOA giúp phân rã theo quyền sở hữu; chỗ nào mơ hồ về chủ sở hữu thì còn tách được nữa.
- Đổi kiến trúc một hệ có trạng thái đang chạy rất phức tạp; cần công cụ (shadow), tự động hoá và "tay chậm mà chắc".
Bài học cho SWE
- Tách dữ liệu theo vòng đời (đang chạy và đã xong) trước khi shard: mỗi phần có mẫu truy cập khác nhau (Chọn database theo workload).
- Service trước DB là bước chuẩn bị để shard mà không phải sửa mọi client (Sharding và tách database).
- Sinh ID xen kẽ chẵn/lẻ là mẹo tạm thời để hai master cùng ghi trong lúc chuyển (Sinh ID phân tán).
- Shadow proxy năm 2014 là tiền thân của các kỹ thuật shadow/parallel run sau này (Grab 2016, Zalando 2021) (Migration không downtime).
Liên quan
Được nhắc tới trong
Công ty (1)
Bài tóm tắt (2)