- SQLite rất nhanh. Trên một máy chủ phổ thông đơn lẻ khoảng ~40€/tháng, nó có thể duy trì đồng thời ~168.000 lượt đọc và ~8.000 lượt ghi
- Vì đây là một thư viện nhúng được thiết kế cho các ứng dụng phía client như hệ thống nhúng, điện thoại, ứng dụng desktop, nên cơ sở dữ liệu SQLite phải nằm cùng với máy chủ ứng dụng và không thể được truy cập qua mạng
- Vậy sử dụng SQLite trong tình huống cần một hoặc nhiều máy khác thì sao?
- Một dự án cuối tuần có thể bùng nổ về mức độ phổ biến và cần mở rộng rất nhanh
- Một trong các yêu cầu của CTO có thể là triển khai dịch vụ có tính sẵn sàng cao trên ít nhất 2 trung tâm dữ liệu khác nhau
- Trong vài năm qua, đã xuất hiện một số dự án cố gắng cải biến SQLite thành cơ sở dữ liệu backend cho các ứng dụng backend.
- Đây là bài viết tìm hiểu xem liệu điều đó có phải là một bước chuyển mô hình giúp các tổ chức cung cấp trải nghiệm người dùng tốt hơn nhanh hơn, hay chỉ là chiêu trò marketing do các công ty cố thổi phồng "điểm bán hàng độc nhất (Unique Selling Proposition)" của mình
Sử dụng SQLite như cơ sở dữ liệu biên
- SQLite đang được quảng bá không chỉ như một cơ sở dữ liệu backend đơn thuần mà còn là cơ sở dữ liệu biên
- Những cái tên tiêu biểu nhất là Cloudflare D1, fly.io dùng LiteFS, và Turso
- Hầu hết các sản phẩm phái sinh từ SQLite đều hoạt động theo cách tương tự
- Có một cơ sở dữ liệu chính ở đâu đó nhận các lượt ghi, rồi được sao chép bất đồng bộ sang các khu vực khác
- Việc sao chép chủ yếu được thực hiện bằng cách stream Write-Ahead Log của SQLite, tức bản ghi của mọi transaction đã chạy trên cơ sở dữ liệu
- Với kiến trúc này, về lý thuyết các lượt đọc có thể được xử lý tại các trung tâm dữ liệu biên, nhưng các lượt ghi vẫn phải được chuyển về vị trí trung tâm
- Trên thực tế, sẽ không ai muốn khách hàng vừa hoàn tất đơn hàng trên một ứng dụng thương mại điện tử, đơn hàng đã được chấp nhận trong cơ sở dữ liệu SQLite chính, nhưng bản sao đọc ở khu vực vẫn bị trễ nên chưa nhận được dữ liệu cập nhật và hiển thị lỗi không tìm thấy
- Chào mừng đến với "thế giới đau khổ của Eventual Consistency"
Giải pháp và giới hạn của LiteFS
- LiteFS đề xuất một giải pháp kiểu chắp vá. Ứng dụng đặt cookie
__txidđể theo dõi transaction cuối cùng mà bản sao khu vực đang có, và nếu quá cũ thì chuyển truy vấn đọc về cơ sở dữ liệu chính. - Giờ đây ứng dụng bị gắn chặt với cơ sở dữ liệu và reverse proxy
- LiteFS cũng không nhắc đến thực tế là nó chỉ hỗ trợ khoảng 100 lượt ghi mỗi giây
Nhược điểm chính của phần lớn các hệ thống SQLite phân tán
- Phần lớn các hệ thống SQLite phân tán không hỗ trợ transaction tương tác, nơi thực hiện một số tính toán giữa các truy vấn khác nhau trong cùng transaction.
- Chỉ có thể có một transaction ghi hoạt động tại một thời điểm. Với một cơ sở dữ liệu SQLite thông thường, điều này nhìn chung không sao vì đa số thao tác ghi không kéo dài quá vài chục micro giây
- Nhưng khi đưa độ trễ mạng vào giữa ứng dụng và cơ sở dữ liệu SQLite, hệ thống sẽ sụp đổ. Cơ sở dữ liệu bị khóa trong suốt thời gian round-trip của transaction và sẽ bị giới hạn ở chỉ vài lượt ghi mỗi giây
- Turso "giải quyết" việc này bằng batch. Nhiều truy vấn có thể được gom thành một batch để chạy như một transaction duy nhất. Cloudflare D1 thì "giải quyết" vấn đề bằng batch và stored procedure
Nếu đã có một giải pháp đơn giản hơn thì sao?
- Với ứng dụng web, đã có một cách rất đơn giản và mạnh mẽ để làm nó cực nhanh trên toàn cầu: dùng HTTP caching với các header
Cache-ControlvàETag - HTTP caching giúp tránh việc phải dùng các kỹ thuật tương tự cơ sở dữ liệu nhất quán yếu, từ đó ngăn ứng dụng web trở nên quá phức tạp hoặc dễ gặp race condition
- Tác giả bài viết dành nhiều thời gian trong cuốn sách mới "Cloudflare for Speed and Security" để giải thích nhiều chiến lược cache khác nhau, không chỉ giúp ứng dụng web nhanh hơn mà còn có thể xử lý rất nhiều người dùng đồng thời với tài nguyên tối thiểu
Cơ sở dữ liệu như một lớp trừu tượng
- Độ trễ không phải là vấn đề duy nhất mà SQLite phân tán cố giải quyết. Vấn đề còn lại là độ phức tạp trong vận hành.
- Quản lý một cụm máy chủ kết nối qua mạng là việc khó và thường dẫn đến downtime cùng tổn thất doanh thu. Chưa kể việc quản trị cơ sở dữ liệu đòi hỏi quản lý liên tục và văn hóa bảo mật tốt để tránh những thảm họa như GitLab từng gặp vào năm 2017.
- Vì vậy, ý tưởng là đóng gói cơ sở dữ liệu cùng ứng dụng và đặt mọi thứ lên một máy chủ duy nhất
- Điều này ổn khi chỉ có một lập trình viên, nhưng ở các tổ chức lớn thường sẽ có người hoặc cả đội chuyên trách việc bảo trì máy chủ cơ sở dữ liệu
- Đó là lý do cơ sở dữ liệu được truy cập qua socket thay vì thư viện nhúng là một lớp trừu tượng tuyệt vời, bởi nó thực ra không phải là lớp trừu tượng kỹ thuật mà là lớp trừu tượng về tổ chức. Khi phát triển, nó có thể chỉ là một container đơn giản chạy trên máy của lập trình viên; nhưng trong production, nó có thể là bất cứ thứ gì, từ container chạy cùng máy chủ với ứng dụng cho đến cụm phân tán được truy cập qua mạng. Lập trình viên chỉ cần thay một biến cấu hình duy nhất là
DATABASE_URL, còn đội vận hành xử lý toàn bộ phần còn lại - Ngược lại, hệ thống file Unix truyền thống là một lớp trừu tượng không phù hợp cho điện toán phân tán. Tất nhiên có NFS (Network File System), nhưng vì hệ thống file Unix được thiết kế cho truy cập trên một máy đơn nên hiệu năng không thực sự tốt. Trong khi đó, giao thức S3 là một lớp trừu tượng khá tốt để lưu trữ lượng lớn dữ liệu phi cấu trúc theo cách hiệu quả, mở rộng tốt và đáng tin cậy. Lập trình viên chỉ cần dùng SDK tương thích S3 rồi quên nó đi, còn đội vận hành hoặc nhà cung cấp cloud sẽ lo toàn bộ phần hiệu năng, độ bền, độ tin cậy, v.v.
Kết luận
- SQLite thực sự là một cơ sở dữ liệu đáng kinh ngạc, nhưng với phần lớn đội ngũ thì nên tránh SQLite và chọn PostgreSQL thay thế
- Vô số giờ kỹ thuật đã được đổ vào để biến PostgreSQL thành cơ sở dữ liệu backend tốt nhất. Nếu chọn SQLite, sớm muộn bạn cũng sẽ phải tái phát minh những gì PostgreSQL đã có từ lâu, theo cách mong manh và đầy lỗi
- Hiện nay, làn sóng muốn biến SQLite thành cơ sở dữ liệu backend theo tác giả chỉ là một cuộc đảo chính marketing của các công ty bán hạ tầng edge computing, sau khi họ nhận ra rằng điện toán không có lớp lưu trữ dữ liệu thì chẳng là gì cả. Lời khuyên (không được yêu cầu) dành cho họ là nên đầu tư vào HTTP caching thay vì xây CDN rồi ép độ phức tạp lên ứng dụng. Cách đó cho kết quả tốt hơn nhiều
- Vì độ phức tạp bị kéo theo, 99,9% ứng dụng backend sẽ không thu được lợi ích gì khi chuyển ra edge; thay vào đó, họ nên tập trung triển khai chiến lược cache tốt để mang lại trải nghiệm tuyệt vời dưới 100ms trên toàn cầu
- Và đây là điểm mà thử nghiệm dùng SQLite cho ứng dụng phía server kết thúc. Chiến thắng thuộc về PostgreSQL
-
"Người nghiệp dư bàn về chiến thuật, chuyên gia bàn về hậu cần. (Amateurs discuss tactics. Professionals discuss logistics.)"
Để thành công, các hệ thống và quy trình hậu thuẫn, tức hậu cần và quản trị, quan trọng hơn những quyết định chiến thuật tại hiện trường mà chúng giúp tạo điều kiện
Ý kiến của GN⁺
- Đúng như tác giả lập luận, việc dùng SQLite trong phần lớn ứng dụng backend có vẻ chỉ làm tăng độ phức tạp mà không mang lại lợi ích thực chất. Sử dụng một cơ sở dữ liệu đã được kiểm chứng và trưởng thành như PostgreSQL có lẽ là lựa chọn tốt hơn.
- Việc các nhà cung cấp hạ tầng edge computing thúc đẩy SQLite có vẻ là một phần của chiến lược marketing hơn là xuất phát từ ưu thế kỹ thuật. Việc họ đầu tư nhiều hơn vào HTTP caching và CDN sẽ hữu ích hơn cho các nhà phát triển ứng dụng.
- Phần lớn ứng dụng backend chỉ với chiến lược cache phù hợp cũng đã đủ để cung cấp dịch vụ nhanh và có khả năng mở rộng tốt. Nếu không thực sự cần edge computing thì nên tránh sự phức tạp quá mức.
- SQLite phân tán có thể hữu ích trong một số use case cụ thể, nhưng vẫn có vẻ còn nhiều giới hạn để dùng như một giải pháp phổ dụng. Không dễ để đồng thời đáp ứng được tính tiện cho phát triển, hiệu năng và tính nhất quán
- Cuối cùng, điều quan trọng nhất là chọn công nghệ phù hợp với yêu cầu của ứng dụng và năng lực của đội ngũ. Thay vì chạy theo xu hướng, cần phân tích kỹ ưu nhược điểm và đưa ra quyết định cẩn trọng.
- Tác giả nhấn mạnh rằng SQLite vẫn còn nhiều điểm chưa đủ để dùng làm cơ sở dữ liệu backend, nhưng có thể vẫn tồn tại những use case khác tận dụng được ưu điểm của SQLite nên không nhất thiết phải loại bỏ hoàn toàn nó.
3 bình luận
Thay vì hỏi giữa Postgres và sqlite cái nào là lựa chọn tốt nhất,
chẳng phải sẽ tốt hơn nếu cân nhắc xem trong hai cái đó, cái nào phù hợp hơn với hoàn cảnh của mình sao?
Vì tùy tình huống mà lựa chọn tối ưu sẽ khác nhau.
Ý kiến Hacker News