10 điểm bởi GN⁺ 2024-04-15 | 2 bình luận | Chia sẻ qua WhatsApp
  • Redka đặt mục tiêu hiện thực lại các ưu điểm của Redis bằng SQLite, đồng thời đảm bảo tương thích với API của Redis
  • Các đặc điểm chính:
    • Dữ liệu không cần phải vừa với dung lượng RAM
    • Hỗ trợ giao dịch ACID
    • Tăng cường khả năng truy vấn dữ liệu và lập báo cáo thông qua SQL view
    • Hỗ trợ cả máy chủ in-process (Go API) và standalone (RESP)
    • Hỗ trợ lệnh và giao thức tương thích Redis
  • Hiện dự án vẫn đang trong quá trình phát triển, tình trạng hỗ trợ và lộ trình có thể xem trong tài liệu bên dưới

Lệnh được hỗ trợ

  • Redka hướng tới việc hỗ trợ 5 kiểu dữ liệu cốt lõi của Redis là String, List, Set, Hash, Sorted Set
  • String, Hash, quản lý Key và các lệnh giao dịch đã được hỗ trợ; List, Set, Sorted Set đang được phát triển
  • Danh sách lệnh chi tiết xem trong nguyên bản

Cách cài đặt

Máy chủ standalone

  • Tải file nhị phân phù hợp với hệ điều hành từ trang Release rồi chạy
  • Nếu dùng Docker, tải image bằng docker pull nalgeon/redka

Mô-đun Go

  • Cài mô-đun bằng go get github.com/nalgeon/redka
  • Dùng github.com/mattn/go-sqlite3 hoặc modernc.org/sqlite làm driver SQLite

Cách sử dụng

Máy chủ standalone

  • Chạy file nhị phân đã tải theo dạng redka [-h host] [-p port] [db-path]
    • Mặc định là host localhost, port 6379, không có đường dẫn DB (in-memory)
  • Nếu dùng Docker thì chạy bằng lệnh docker run. Các tùy chọn chi tiết xem nguyên bản
  • Sau khi khởi động máy chủ, có thể kết nối bằng các client tương thích Redis như redis-cli, redis-py, go-redis

Máy chủ in-process

  • Tạo đối tượng DB bằng hàm redka.Open(). Bắt buộc phải import driver
  • Gọi các phương thức của đối tượng redka.DB để thực thi các lệnh khác nhau
  • Xử lý giao dịch bằng các phương thức View (chỉ đọc) và Update (cho phép ghi)

Tính bền vững dữ liệu

  • Redka lưu dữ liệu trong cơ sở dữ liệu SQLite bằng các bảng rkey, rstring, rhash
  • Có thể truy vấn dữ liệu bằng SQL thông qua các view theo từng kiểu dữ liệu (vstring, vhash, v.v.)

Hiệu năng

  • So sánh hiệu năng giữa Redis và Redka bằng công cụ redis-benchmark
    • Redka chậm hơn khoảng 6 lần ở SET và khoảng 2 lần ở GET
    • Dù vậy vẫn cho thấy hiệu năng ở mức 23K writes/giây, 57K reads/giây
  • Hiệu năng có thể giảm nếu chạy trong container

Lộ trình

  • Bản phát hành 1.0 dự kiến sẽ tập trung hiện thực các tính năng chính từ thời Redis 2.x
    • Đã hoàn tất hỗ trợ String, Hash, quản lý Key và giao dịch
    • Sorted Set đang được phát triển
    • List, Set sẽ được phát triển tiếp
  • Trong các phiên bản sau, dự kiến bổ sung các kiểu dữ liệu như Stream, HyperLogLog, Geo và tính năng Pub/Sub
  • Không có kế hoạch hiện thực Lua scripting, authentication/ACL, multi DB, Watch/Unwatch
  • Cũng không dự định hiện thực tính năng cluster và sentinel

Ý kiến của GN⁺

  • Cách tiếp cận của Redka khá thú vị khi vẫn tương thích phần lớn với Redis nhưng lại cung cấp tính bền vững dữ liệu. Việc hỗ trợ giao dịch ACID cũng có vẻ là một lợi thế.
  • Về hiệu năng, Redka chưa thể sánh với Redis, nhưng nếu cần tính bền vững thì đây vẫn có thể là một lựa chọn thay thế đáng cân nhắc.
  • Tuy nhiên, dự án vẫn đang ở giai đoạn đầu phát triển nên cần theo dõi thêm về độ ổn định; ngoài ra cũng có khá nhiều tính năng chưa có trong lộ trình mà cần cân nhắc khi triển khai thực tế.
  • Dùng cho mục đích in-memory thì cuối cùng vẫn khó vượt qua Redis, nhưng với vai trò một lớp bền vững dữ liệu dựa trên SQLite thì có thể khá hữu ích.
  • Gần đây nhu cầu về các stack nhẹ trong môi trường edge computing đang tăng cao, nên trong những lĩnh vực như vậy có thể thử dùng Redka thay cho Redis.

2 bình luận

 
yangeok 2024-05-10

Có vẻ sẽ khá hữu ích khi cần gắn Redis vào scheduler nhỉ haha

 
GN⁺ 2024-04-15
Ý kiến trên Hacker News
  • Có suy nghĩ về việc sẽ đi theo mô hình không có tính đồng thời của Redis, nơi "mọi thứ được tuần tự hóa trên một luồng duy nhất", đến mức nào
  • Có thể đạt hiệu năng tốt hơn từ SQLite nếu dùng thư viện cấp thấp của SQLite, bật WAL, dùng một kết nối cho mỗi goroutine chỉ đọc, và gửi các lô ghi qua channel/hàng đợi có bộ đệm tới một luồng writer chuyên dụng
  • Nhờ vậy có thể tắt mutex tích hợp theo từng kết nối của SQLite mà vẫn giữ được an toàn luồng, vì mỗi kết nối chỉ được dùng bởi một luồng tại một thời điểm
  • Nếu dùng các bộ đệm lớn kiểu arena, như sao chép byte tham số đi vào từ request/socket mạng vào buffer hoặc sao chép trực tiếp từ SQLite ra socket, có thể giảm việc cấp phát và truyền từng chuỗi riêng lẻ, từ đó tiết kiệm đáng kể thời gian
  • Đây là các mẹo rút ra từ kinh nghiệm cố gắng đạt thông lượng ghi tối đa từ SQLite trong Go
  • Vì thích cả Redis lẫn SQLite nên đã quyết định kết hợp hai thứ này. SQLite rất phù hợp với nhiều truy vấn nhỏ, nên có vẻ là lựa chọn tốt vì engine quan hệ này đã tiến gần Redis nhất có thể
  • Đang chờ ai đó thay thế state machine của TigerBeetle để triển khai Redis API
  • Sẽ rất tuyệt nếu có một giải pháp thay thế Redis mà không cần nghĩ xem tập dữ liệu có vừa trong bộ nhớ hay không
  • Toàn bộ giá trị cốt lõi của Redis là hoạt động trong bộ nhớ và mang lại hiệu năng như bộ nhớ. Khi chuyển sang đĩa thì gần như không còn nhiều lý do để dùng Redis
  • Khi thêm network I/O, phần lớn hiệu năng tuyệt vời của Redis sẽ biến mất. Dùng dịch vụ Redis lưu trữ kiểu SaaS sẽ khiến hiệu năng bị ảnh hưởng nặng. Nếu có thể chạy một kho khóa/giá trị tương thích Redis dễ dàng hơn trên cụm tự quản, đó sẽ là một lợi thế
  • Không rõ cái này hay Garnet hỗ trợ được nhiều lệnh Redis hơn. Tôi đang muốn nhúng một tập con tính năng tương thích Redis vào chương trình cho mục đích debug cục bộ, và có một lớp API ở giữa để chặn các lệnh Redis không được hỗ trợ
  • Khi Foursquare khiến MongoDB trở nên nổi tiếng, đã có người đăng một PoC về cơ sở dữ liệu NoSQL triển khai trên MySQL nhưng nó không thành trào lưu. Tuy vậy, điều đó khiến người ta nghĩ về việc đã hy sinh bao nhiêu hiệu năng để khỏi phải tái phát minh SQL mỗi khi cần một DB. Tôi thích những thử nghiệm như thế này, và đôi khi chúng dẫn đến các dự án mới
  • Dùng Redis như một lớp cache trước DB. Tôi không hiểu khái niệm này
  • Tuy nhiên, đang dùng SetMaxConnections(1), nhưng ở chế độ WAL (đang dùng), SQLite hỗ trợ ghi mà không chặn đọc, nên có thể sẽ có lợi nếu cho phép đồng thời ở phía đọc