Mục lục
Giới Thiệu: Sự Ra Đời Của Aurora DSQL
Tại sự kiện re:Invent, chúng tôi đã công bố Aurora DSQL – một giải pháp cơ sở dữ liệu mang tính cách mạng. Điều thú vị không chỉ nằm ở công nghệ mà còn ở hành trình đầy thách thức phía sau. Bài viết này sẽ tiết lộ câu chuyện phát triển đầy cam go, từ quyết định chuyển đổi ngôn ngữ lập trình cho đến những bài học quan trọng về scalability trong hệ thống phân tán.
Bối Cảnh: Sự Phát Triển Của Cơ Sở Dữ Liệu Tại AWS
Từ khi ra mắt Amazon RDS năm 2009, AWS đã không ngừng đổi mới để đáp ứng nhu cầu đa dạng của khách hàng. Aurora giải quyết bài toán hiệu năng và chi phí, DynamoDB xử lý workload NoSQL quy mô internet, trong khi Redshift tối ưu cho phân tích dữ liệu lớn. Mỗi dịch vụ ra đời đều là lời giải cho những thách thức cụ thể trong thực tế.
Tuy nhiên, một câu hỏi lớn vẫn tồn tại: Làm thế nào để xây dựng một cơ sở dữ liệu quan hệ không cần quản lý hạ tầng, tự động scale theo tải, đồng thời duy trì sức mạnh của SQL cùng khả năng triển khai đa vùng liền mạch? Aurora DSQL chính là câu trả lời cho bài toán này.
Kiến Trúc Cốt Lõi Của Aurora DSQL
DSQL được thiết kế theo triết lý Unix – mỗi component thực hiện một nhiệm vụ cụ thể nhưng kết hợp lại tạo thành một hệ thống hoàn chỉnh với đầy đủ tính năng: giao dịch, độ bền, truy vấn, isolation, consistency, recovery, concurrency và hiệu năng.
Kiến trúc DSQL giải quyết bài toán scaling theo hai hướng:
- Xử lý đọc: Đã được tối ưu từ năm 2021
- Xử lý ghi: Bài toán khó khăn hơn nhiều với yêu cầu scaling ngang
Giải pháp truyền thống là sử dụng two-phase commit (2PC), nhưng phương pháp này đối mặt với nhiều thách thức về độ phức tạp nghiệp vụ và khả năng chịu lỗi. Nhóm phát triển đã tìm ra cách tiếp cận mới – ghi toàn bộ commit vào một journal duy nhất thay vì phân tán theo rows.
Crossbar – Bước Đột Phá Trong Kiến Trúc
Để giải quyết bài toán scaling, nhóm đã phát triển Crossbar – lớp kiến trúc tách biệt đường đọc và đường ghi. Crossbar cung cấp API subscription cho storage, cho phép các node storage đăng ký theo dõi các key trong phạm vi cụ thể.
Thử Thách Hiệu Năng Và Quyết Định Chuyển Sang Rust
Các bài test mô phỏng với 40 hosts cho thấy kết quả đáng báo động:
- Chỉ đạt 6,000 TPS thay vì mục tiêu 1 triệu TPS
- Độ trễ đuôi (tail latency) tăng từ 1 giây lên 10 giây
Nguyên nhân chính đến từ vấn đề garbage collection trong JVM. Nhóm đã đứng trước ba lựa chọn:
- Tối ưu hóa JVM
- Chuyển sang C/C++
- Áp dụng Rust – giải pháp cuối cùng được lựa chọn
Thành Công Ban Đầu Với Rust
Bắt đầu với component Adjudicator tương đối đơn giản, kết quả khiến cả team bất ngờ:
- Code Rust chạy nhanh gấp 10 lần bản Kotlin đã được tối ưu
- Đạt 30,000 TPS so với 3,000 TPS của phiên bản trước
Tích Hợp PostgreSQL Với Rust
Thay vì fork PostgreSQL, nhóm quyết định tận dụng các điểm mở rộng (extension points) – một trong những thiết kế mạnh mẽ nhất của PostgreSQL. Quyết định quan trọng nhất là viết các extension bằng Rust thay vì C, nhờ đó:
- Giảm thiểu lỗi memory safety
- Tận dụng hệ sinh thái Crates.io
- Duy trì khả năng tương thích với upstream
Control Plane: Từ Kotlin Quay Trở Lại Rust
Ban đầu, control plane được viết bằng Kotlin do các ưu điểm về thư viện và năng suất. Tuy nhiên, khi tích hợp với data plane, các vấn đề phát sinh:
- Không thể chia sẻ logic nghiệp vụ chung
- Khác biệt ngôn ngữ dẫn đến sai lệch trong triển khai
- Khó khăn trong việc chia sẻ platform testing
Sau một năm, team đã mạnh dạn chuyển toàn bộ control plane sang Rust nhờ:
- Cải tiến trong Rust 2021 Edition
- Thư viện nội bộ đã phát triển đầy đủ
- Tinh thần học hỏi mạnh mẽ từ đội ngũ
Kết Quả Cuối Cùng Và Bài Học Kinh Nghiệm
Rust đã chứng minh là lựa chọn hoàn hảo cho DSQL:
- Hiệu năng vượt trội, đặc biệt về tail latency
- Bảo mật memory mà không hy sinh hiệu suất
- Năng suất không thua kém JVM khi team đã làm quen
Tuy nhiên, bài học lớn nhất là không có giải pháp phù hợp cho mọi bài toán. Việc lựa chọn ngôn ngữ cần dựa trên:
- Yêu cầu cụ thể của hệ thống
- Năng lực của team
- Môi trường vận hành