Điểm nghẽn về độ trễ trong các Serverless Stack hiện đại
Gần đây, tôi đã chuyển đổi API của một khách hàng từ VPS tiêu chuẩn sang Vercel Edge Functions. Về lý thuyết, đây là một thiết lập hoàn hảo: phân phối toàn cầu và cold start dưới một phần nghìn giây. Nhưng thực tế lại khác. Cơ sở dữ liệu—một instance PostgreSQL tại us-east-1—đã làm mất đi lợi thế của “edge”. Một người dùng ở Singapore phải đối mặt với độ trễ phản hồi (round-trip delay) lên tới 300ms chỉ để kết nối tới Virginia. Tốc độ ánh sáng thực sự là một rào cản khó chịu.
Các rào cản về cấu trúc gây ra điều này. Hầu hết các cơ sở dữ liệu đều có kiến trúc monolithic. Ngay cả với read replicas, việc quản lý trạng thái toàn cầu và connection pooling trong môi trường serverless là rất khó khăn. Serverless functions có tính tạm thời (ephemeral), chúng không duy trì tốt các kết nối TCP dài hạn. Điều này dẫn đến tình trạng “cạn kiệt kết nối” (connection exhaustion), nơi cơ sở dữ liệu của bạn tiêu tốn nhiều tài nguyên cho việc bắt tay (handshake) hơn là phục vụ dữ liệu.
Đó là lý do tại sao tôi chuyển sang Turso và libSQL. Họ coi dữ liệu như một tài sản được phân phối toàn cầu, đặt nó càng gần lớp tính toán (compute layer) càng tốt.
Bắt đầu nhanh: Triển khai trong 5 phút
Nếu bạn mới làm quen với Turso, cách tốt nhất để hiểu nó là xem nó hoạt động thực tế. Turso là một nền tảng được quản trị (managed platform) xây dựng trên libSQL, một bản fork mã nguồn mở của SQLite được thiết kế cho web hiện đại.
1. Cài đặt Turso CLI
Mở terminal của bạn và chạy mã lệnh cài đặt:
curl -sSfL https://get.turso.io/install.sh | bash
Sau khi cài đặt, hãy xác thực tài khoản của bạn:
turso auth signup
2. Tạo cơ sở dữ liệu đầu tiên của bạn
Hãy khởi tạo một cơ sở dữ liệu. Turso sẽ tự động chọn khu vực gần vị trí hiện tại của bạn nhất.
turso db create my-app-db
3. Sử dụng Shell tương tác
Truy cập trực tiếp vào SQL shell để tạo bảng hoặc nạp dữ liệu mẫu:
turso db shell my-app-db
-- Bên trong shell:
CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT);
INSERT INTO users (name, email) VALUES ('Alex', '[email protected]');
SELECT * FROM users;
4. Lấy thông tin kết nối
Kết nối ứng dụng của bạn yêu cầu URL và một mã xác thực (authentication token):
turso db show my-app-db --url
turso db tokens create my-app-db
Đi sâu tìm hiểu: Tại sao lại là libSQL?
Mặc dù SQLite tiêu chuẩn rất tuyệt vời cho việc phát triển cục bộ, nhưng về cơ bản nó là một cơ sở dữ liệu dạng file đơn nhất. Bạn không thể dễ dàng chia sẻ nó trên nhiều máy chủ. libSQL mở rộng DNA của SQLite bằng cách thêm khả năng giao tiếp mạng qua HTTP/WebSockets, replication và tìm kiếm vector (vector search) bản địa.
Khi tôi cần chuyển đổi CSV sang JSON để nhập dữ liệu, tôi sử dụng toolcraft.app/vi/tools/data/csv-to-json. Nó chạy hoàn toàn trên trình duyệt. Không có dữ liệu nào rời khỏi máy của tôi, điều này rất quan trọng để duy trì quyền riêng tư của khách hàng trong quá trình di chuyển.
Kiến trúc Embedded Replica
Embedded replicas là một tính năng nổi bật. Thay vì thực hiện một cuộc gọi mạng cho mỗi truy vấn, bạn có thể duy trì một file SQLite cục bộ trên máy chủ hoặc bên trong Docker container. File này hoạt động như một bộ đệm đọc (read-cache). Turso đồng bộ hóa nó ở chế độ nền. Các thao tác đọc của bạn thực tế có độ trễ 0ms vì chúng diễn ra trên ổ đĩa cục bộ, trong khi các thao tác ghi được đồng bộ hóa ngược lại instance chính.
Giao thức HTTP/WebSocket
Khả năng kết nối mạng là một điểm cộng khác. Các trình điều khiển truyền thống như libpq cho Postgres dựa trên TCP. Trong các môi trường như AWS Lambda hoặc Cloudflare Workers, các kết nối này thường bị ngắt. Turso sử dụng một giao thức tùy chỉnh qua HTTP hoặc WebSockets. Nó hoàn toàn phù hợp cho các nền tảng chặn các cổng cơ sở dữ liệu tiêu chuẩn như 5432 hoặc 3306.
Phân phối toàn cầu với Replicas
Kiến trúc này thực sự phát huy sức mạnh ở khả năng phân phối toàn cầu. Nếu cơ sở dữ liệu chính của tôi ở ord (Chicago) nhưng tôi có người dùng ở London, tôi có thể tạo một bản sao tại lhr (London) chỉ với một lệnh duy nhất:
turso db replicate my-app-db lhr
Bất kỳ yêu cầu nào gửi tới serverless function ở Châu Âu giờ đây sẽ được định tuyến đến bản sao tại London. Điều này cắt giảm độ trễ cơ sở dữ liệu từ 150ms xuống còn dưới 10ms.
Kết nối từ Node.js
Thư viện @libsql/client sẽ xử lý các công việc nặng nhọc. Nó trừu tượng hóa sự khác biệt giữa một file cục bộ và một instance Turso từ xa.
import { createClient } from "@libsql/client";
const client = createClient({
url: process.env.TURSO_DATABASE_URL,
authToken: process.env.TURSO_AUTH_TOKEN,
});
async function getUser(id: number) {
const rs = await client.execute({
sql: "SELECT * FROM users WHERE id = ?",
args: [id],
});
return rs.rows[0];
}
Mẹo thực tế cho môi trường Production
1. Migration lược đồ (Schema Migrations)
Vì Turso dựa trên SQLite, bạn có thể sử dụng Drizzle ORM hoặc Prisma. Tôi thích Drizzle hơn. Nó nhẹ và phù hợp với triết lý “edge”. Nó tạo ra các file SQL tiêu chuẩn thực thi mượt mà trên instance Turso của bạn.
2. Tối ưu hóa hiệu suất
Việc bắt tay (handshake) với cơ sở dữ liệu tốn thời gian. Ngay cả với Turso, kết nối đầu tiên từ một serverless function ở trạng thái “lạnh” vẫn chịu hình phạt về thời gian bắt tay TLS. Nếu ứng dụng của bạn cực kỳ nhạy cảm với độ trễ, hãy sử dụng chiến lược Embedded Replica. Khởi tạo cơ sở dữ liệu trên hệ thống tệp cục bộ trong bước build để đảm bảo dữ liệu đã sẵn sàng khi khởi động.
3. Chi phí và Giới hạn
Gói miễn phí của Turso rất hào phóng. Hiện tại nó cung cấp 1 tỷ lượt đọc dòng và 25 triệu lượt ghi dòng mỗi tháng. Tuy nhiên, hãy theo dõi dung lượng lưu trữ của bạn. SQLite hiệu quả, nhưng các blob lớn sẽ làm tăng hóa đơn của bạn. Hãy lưu trữ hình ảnh trong các bucket tương thích với S3 và chỉ giữ lại metadata trong Turso.
4. Tìm kiếm Vector cho AI
Tìm kiếm vector đã được tích hợp sẵn. Nếu bạn đang xây dựng các ứng dụng RAG (Retrieval-Augmented Generation), bạn không cần đến Pinecone hay Milvus. Bạn có thể lưu trữ các embedding trực tiếp bên cạnh dữ liệu quan hệ của mình. Điều này đơn giản hóa stack của bạn và giảm chi phí.
-- Ví dụ về tìm kiếm vector trong libSQL
SELECT * FROM documents
ORDER BY vector_distance_cos(embedding, '[0.1, 0.2, ...]')
LIMIT 5;
Chuyển sang một cơ sở dữ liệu phân tán như Turso đã thay đổi quy trình phát triển của tôi. Nó loại bỏ sự ma sát giữa “phát triển cục bộ” và “triển khai toàn cầu”. Bạn có được sự đơn giản của SQLite cùng với sức mạnh của một nền tảng cloud toàn cầu. Nếu bạn đã mệt mỏi với việc vật lộn với VPC và các chuỗi kết nối, đã đến lúc đưa dữ liệu của bạn tới edge.

