12 điểm bởi xguru 2024-09-26 | 7 bình luận | Chia sẻ qua WhatsApp
  • Wafris là một công ty tường lửa ứng dụng web mã nguồn mở cung cấp client middleware cho Rails
  • Client v1 yêu cầu kho lưu trữ dữ liệu Redis cục bộ, nhưng v2 sử dụng SQLite
  • Bài viết giải thích bối cảnh quyết định di chuyển từ Redis sang SQLite, các cân nhắc về hiệu năng và những thay đổi về kiến trúc

TL;DR

  • SQLite có những việc làm tốt và những việc làm không tốt
  • Redis có những việc làm tốt và những việc làm không tốt
  • RDBMS truyền thống (Postgres/MySQL) có những việc làm tốt và những việc làm không tốt
  • Không thể thay trực tiếp các kho dữ liệu này cho nhau, và nếu cố làm vậy thì sẽ gặp rắc rối
  • Bài viết này mô tả quá trình thử nghiệm và ra quyết định khi tái kiến trúc client v1 dựa trên Redis thành client v2 dựa trên SQLite

Những yếu tố buộc phải thay đổi

  • Mục tiêu của Wafris là giúp các nhà phát triển dễ dàng bảo vệ website của họ
  • v1 đã không đạt trọn vẹn mục tiêu này do các vấn đề triển khai Redis
  • Redis được chọn vì nhóm làm việc trong các môi trường như Heroku, nơi Redis rất dễ dùng, nhưng nhiều người dùng đã gặp vấn đề khi triển khai Redis
  • Việc bắt người dùng phải dùng một DB riêng như Redis không phải là điều tốt cho họ

“Tốc độ” là gì?

  • Redis “nhanh hơn” RDBMS truyền thống, nhưng vẫn cần quản lý kết nối, bộ nhớ, tiến trình, v.v.
  • Trong môi trường cloud, độ trễ mạng có thể là một vấn đề lớn
  • Vì Wafris phải đánh giá rule cho mỗi HTTP request đi vào, độ trễ mạng có thể làm chậm ứng dụng

Giả định kiểu monolith

  • Dù vẫn có những ứng dụng phân tán hoàn toàn, phần lớn ứng dụng Rails là “Majestic Monoliths”
  • Các ứng dụng được triển khai ở nhiều vùng, tách thành các server có chức năng chồng lấn, hoặc chỉ một phần dùng Rails sẽ gặp nhiều vấn đề hơn khi dùng Redis

Suy nghĩ lại về kiến trúc

  • Wafris là một tường lửa ứng dụng web được cài dưới dạng middleware Rails
  • Nếu chia đơn giản, nó có 2 bước: 1) so khớp HTTP request với các rule, 2) báo cáo kết quả xử lý
  • Việc “đọc” rule (bước 1) quan trọng hơn nhiều so với việc “ghi” (bước 2)
  • Việc đọc phải được xử lý tuần tự, không được thất bại, và ảnh hưởng đến hiệu năng mà người dùng cảm nhận
  • Việc ghi có thể chậm hơn, xử lý theo lô hoặc bất đồng bộ

SQLite xuất hiện

  • Nhiều người khác đã giải thích rất rõ các trường hợp sử dụng phù hợp của SQLite
  • SQLite không cạnh tranh với DB client/server mà cạnh tranh với fopen()
  • Khi loại bỏ được một vòng network round-trip, nhóm kỳ vọng nó sẽ nhanh hơn Redis rất nhiều
  • Vì vậy họ quyết định benchmark SQLite và Redis

Benchmark SQLite và Redis

  • Benchmarking là một nghệ thuật đen tối, nơi bạn dễ tự đánh lừa mình bằng các con số tưởng như chính xác
  • Benchmark kho dữ liệu còn khó hơn nữa
  • Mục tiêu không phải tìm ra tốc độ tuyệt đối mà là tạo benchmark đặc thù cho dữ liệu và trường hợp sử dụng của họ
  • Họ bỏ qua các tinh chỉnh tối ưu. Khi thêm Wafris vào ứng dụng, họ muốn nó hoạt động ngay
  • Họ kiểm tra đường đi quan trọng và truy vấn tệ nhất trong ứng dụng của mình, không phải benchmark mang tính lý thuyết
  • Truy vấn tệ nhất là một yêu cầu trên cấu trúc dữ liệu “lexical decimal” phức tạp, ánh xạ các dải IP (IPv4, IPv6) sang danh mục
  • Việc tra cứu theo dải được tính toán sẵn để ghi vào bảng SQLite và sorted set của Redis
  • Với mỗi HTTP request đi vào, cần so sánh IP của request với các dải tùy chỉnh cho phép/chặn, các dải GeoIP và các dải uy tín IP

Giao thức thử nghiệm

  • Thử nghiệm được thực hiện trên MacBook Air M2 với Redis cài bằng Homebrew và DB SQLite cục bộ
  • Họ thử trên bộ dữ liệu dải hiện có gồm 1,2 triệu mục
  • Nhiều tập IP được chạy theo cùng một thứ tự trên cả SQLite và Redis
  • Mỗi mức nhân được chạy thử 5 lần rồi lấy trung bình

Kết quả thử nghiệm

  • SQLite thắng áp đảo Redis (trong trường hợp sử dụng rất đặc thù của họ)
  • SQLite nhanh hơn khoảng 3 lần so với một instance Redis cục bộ
  • Đây là kết quả còn chưa tính đến độ trễ mạng
  • Ngay cả khi SQLite chỉ ngang Redis, việc loại bỏ thời gian mạng vẫn đã là một lợi thế

Những gì không xuất hiện trên biểu đồ

  • Ngay cả khi hiệu năng SQLite tệ hơn benchmark 2 lần, trong thực tế nó vẫn có thể nhanh hơn do độ trễ mạng
  • Dù server Redis có mạnh đến đâu vẫn tồn tại giới hạn về băng thông mạng, kết nối, cũng như độ trễ liên vùng
  • SQLite gần như có thể mở rộng theo chiều ngang vô hạn một cách “miễn phí”
  • Việc onboarding với SQLite tốt hơn rất nhiều. Có thể người dùng thậm chí không nhận ra nó đang được dùng
  • Vẫn có thể vắt thêm hiệu năng từ Redis, nhưng rất khó thuyết phục người dùng thay đổi cấu hình Redis của họ

Kết quả mới chỉ là khởi đầu

  • Dù đã chứng minh SQLite nhanh hơn Redis, vẫn có những đánh đổi thực tế
  • Bài thử phía trên không tính đến việc ghi
  • Để quản lý cạnh tranh giữa đọc và ghi, vẫn cần các thứ như kết nối DB, connection pool, transaction, v.v.
  • Giống như một siêu xe điện khó mà chở được khối bê tông lớn, SQLite không nên bị dùng cho những vai trò không phù hợp

Xây dựng kiến trúc đồng bộ hóa

  • Trong v1 (Redis), khi người dùng cập nhật rule trên Wafris Hub, các rule trong kho dữ liệu Redis sẽ được cập nhật
  • Với SQLite, không thể “push” đến web server nên cách đó không hoạt động
  • Trong v2 (SQLite): 1) người dùng cập nhật rule trên Wafris Hub 2) client định kỳ kiểm tra rule đã cập nhật 3) nếu rule thay đổi thì tải xuống một DB SQLite hoàn toàn mới
  • Điều này giúp giảm mạnh trách nhiệm cài đặt và cấu hình phía người dùng
  • Tỷ lệ cài đặt thành công của client v2 đã tăng gấp 3 lần

Kiến trúc phân tán với SQLite

  • Hãy xét một ứng dụng Rails được triển khai trên nhà cung cấp cloud có bật auto-scaling
  • Khi lưu lượng tăng từ 100req/s lên 10.000req/s, các instance compute sẽ mở rộng nhưng DB thì không
  • Đây thực tế là lý do chính khiến ứng dụng Rails sập khi bị quá tải
  • Đồng bộ DB SQLite đến từng instance compute giúp giải quyết vấn đề này vì mọi lời gọi đều được giữ ở local

Còn việc ghi thì sao?

  • Họ tách ứng dụng thành đường đọc (đánh giá rule) và đường ghi (báo cáo), rồi gần như bỏ qua đường ghi
  • Đường ghi được thiết kế lại thành: 1) kết nối bất đồng bộ tới Wafris Hub để báo cáo 2) gửi báo cáo theo lô 3) loại bỏ hoàn toàn việc ghi DB ở client
  • Cách này có thể không phù hợp với người khác, nhưng họ chỉ quan tâm đến những người dùng muốn một client Wafris dễ triển khai và nhanh

Kết luận

  • Họ rất hài lòng với kiến trúc v2 sử dụng SQLite
  • Nó đã giúp nhiều website chịu được tấn công và duy trì trạng thái online
  • Việc bắt đầu sử dụng trở nên dễ hơn rất nhiều, giảm công việc hỗ trợ của họ và sự phiền toái cho người dùng
  • Họ cho rằng đây là một chiến thắng cho một Internet an toàn và bảo mật hơn

7 bình luận

 
aer0700 2024-09-26

SQLite đủ tốt đấy, nhưng trong trường hợp này thì có cảm giác đơn giản là đây vốn không phải một use case phù hợp với Redis...

 
kandk 2024-09-26

Việc benchmark trên M2 thì hơi...

 
colossus 2024-09-29

Vậy là phải đo trên từng instance AWS sao? Có vẻ bạn đang kỳ vọng quá nhiều vào phần mềm nguồn mở rồi đấy.

 
toru123 2024-09-27

Đều được thực hiện trong cùng một môi trường máy chủ, vậy có thành vấn đề không?
Benchmark thì có cần phải dùng một CPU cụ thể không...?

 
superwoou 2024-09-26

Những điểm nào khi làm trên M2 có thể trở thành vấn đề? (ngoài việc môi trường dịch vụ thực tế không dùng bộ xử lý M2)

 
kandk 2024-09-26

Đó mới là vấn đề. Thử nghiệm trong phòng thí nghiệm rồi khẳng định rằng thứ này hoàn hảo cho mục đích thương mại!

 
[Bình luận này đã bị ẩn.]