Wix Inbox Journey: 3 Approaches for Zero Downtime Database Migration
Wix · 2021 · 3. Quy mô lớn · Độ khó: Trung bình — bài gốc
Bối cảnh
- Wix có hơn 200 triệu user ở 190 nước. Ứng dụng chat của Wix Inbox (trong bộ CRM) chạy trên Cassandra tự quản lý trên EC2, dùng chung cho nhiều microservice.
- Vì sao không ổn định:
- partition key = chatroom id, mà các phòng chat không đều về traffic lẫn dung lượng, nên tạo hot spot, có node crash;
- mẫu truy cập mới không dùng đủ khoá chính, buộc phải thêm secondary index rồi materialized view;
- rất ít người ở Wix hiểu Cassandra đủ sâu để vận hành.
Thay đổi chính
Nguyên tắc chính (theo Wix): hiểu sâu dữ liệu thì mới chọn đúng công nghệ và cách migrate. Tạm gác công nghệ quen sang một bên, trả lời trước: mẫu truy cập (đọc, ghi, một hay nhiều region, SLA); dữ liệu có thay đổi sau khi ghi không; có giới hạn thời gian không; có cần biến đổi schema không; dung lượng bao nhiêu. Cả hai trường hợp dưới đây cuối cùng đều chọn DynamoDB.
Ba cách migrate:
-
Theo vòng đời (dữ liệu online/offline của khách truy cập site: sống ngắn nhờ TTL, mỗi lần ghi ghi đè toàn bộ, không đổi schema):
- ghi kép Cassandra rồi DynamoDB, một trong hai lỗi thì cả request lỗi (vì ghi đè toàn bộ, retry vẫn nhất quán);
- chờ hết một vòng đời dữ liệu thì hai bên giống nhau;
- chuyển đọc/ghi sang bên mới, rồi bỏ bên cũ.
Cho tới lúc chuyển hẳn vẫn ghi vào Cassandra, nên rollback được bất cứ lúc nào.
-
Lặp toàn bộ kiểu kinh điển (tin nhắn: vài TB, vĩnh viễn, bất biến, nhưng phải đổi schema):
- ghi kép, lúc đầu ghi DynamoDB trong try/catch chỉ báo lỗi ("shadow mode", để DynamoDB "ấm" lên rồi mới đưa vào đường chính);
- clone snapshot Cassandra làm nguồn migrate.
Thử trên một bảng nhỏ phát hiện: không biết tiến độ (dù có metric) và clone bị thiếu dữ liệu. Họ bỏ cách này.
-
Tăng dần theo entity (cho tin nhắn):
- bảng Chatroom Migration State lưu trạng thái migrate của từng phòng;
- phòng mới tạo được đánh dấu "đã migrate" ngay;
- mỗi lần đọc kiểm tra trạng thái để đọc từ DynamoDB hay Cassandra;
- theo thời gian, lượng đọc vào Cassandra giảm, rồi mới migrate phòng cũ từng tháng một, lùi dần về quá khứ.
Kết quả: biết chắc phòng nào đã xong, chuyển dần không có "điểm đỉnh", rollback được tới phút cuối. Có thể để lại dữ liệu rất cũ ở DB cũ nếu không cần bỏ hẳn nó.
Đánh đổi
Ghi kép tốn thêm tài nguyên ứng dụng (heap, CPU, GC) và tăng một chút latency ghi. Bước kiểm tra trạng thái thêm chút thời gian cho mỗi lần đọc nhưng không đáng kể.
Bài học cho SWE
- Thuộc tính của dữ liệu quyết định cách migrate: dữ liệu sống ngắn thì chờ hết vòng đời; dữ liệu bất biến thì chép thoải mái; dữ liệu truy cập theo entity thì migrate tăng dần theo entity.
- Cho kho mới nhận traffic thật sớm (shadow) và luôn có đường rollback (vẫn ghi vào kho cũ).
- Migrate theo đơn vị nghiệp vụ (phòng chat) cho biết chính xác tiến độ, tốt hơn lặp qua toàn bộ dữ liệu một cách mù.
- Partition key không đều (chatroom) tạo hot spot, cùng bài toán với Discord (Discord 2023).