SableDb – Fast, persistent database supporting Redis API
github.com
github.com
I will release some design documents later on (hopefully this month). Remember that is a one man project (hopefully, not for long), so it takes time to organize everything :)
Each incoming connection is assigned to a worker thread, and two tokio tasks are created for the connection (one for reading and another for writing).
Using tokio allowed me to use the `async` code without using "callback hell" so the code looks clean and readable in a single glance without the need to follow callbacks
KVRocks
PING_INLINE: 171821.30 requests per second, p50=0.183 msec
PING_MBULK: 173310.22 requests per second, p50=0.191 msec
SET: 115074.80 requests per second, p50=0.399 msec
GET: 163398.70 requests per second, p50=0.271 msec
INCR: 110741.97 requests per second, p50=0.415 msec
LPUSH: 89847.26 requests per second, p50=0.487 msec
RPUSH: 94428.70 requests per second, p50=0.487 msec
LPOP: 86880.97 requests per second, p50=0.535 msec
RPOP: 88339.23 requests per second, p50=0.527 msec
SableDB PING_INLINE: 90744.10 requests per second, p50=0.279 msec
PING_MBULK: 90826.52 requests per second, p50=0.279 msec
SET: 85763.29 requests per second, p50=0.311 msec
GET: 87336.24 requests per second, p50=0.295 msec
INCR: 68775.79 requests per second, p50=0.663 msec
LPUSH: 36589.83 requests per second, p50=1.031 msec
RPUSH: 38299.50 requests per second, p50=1.135 msec
LPOP: 38051.75 requests per second, p50=1.191 msec
RPOP: 37383.18 requests per second, p50=1.143 msec
KVRocks seems faster but certainly not a bad startOnce this in place, adding "hash" commands (hset, hget etc) is the next family of commands. I open sourced it hopefully to get help from people out there :)
https://microsoft.github.io/garnet/docs/benchmarking/results...
Besides, I don’t expect SableDB to be faster than weakly persisted systems like Redis or I guess Garnet. The cool thing about SableDB is that it (looks?) durable - although the docs don’t make specific promises, they do mention some things in passing that imply RocksDb transactions. Each command seems to flush its changes to durable storage before succeeding. That’s very different from Redis et al even with their “append only file” / WAL turned on - the AOF is written asynchronously so you will still lose data on crash. Redis also deletes random data when under memory/storage pressure.
Again, I want to understand trade-offs not “find the fastest web scale database”. I’m sure /dev/null is faster than Garnet.
unsafe fn main() {
...
}IMO, the networking, threading and "tasks" ("green threads") in SableDb code base are the most risky part of writing a server and by choosing Rust, the risk of memory issues is reduced to minimum without scarifying performance
I kept the adapter approach in the code, so switching back to sled should be pretty easy (or even converting it to full in-memory)
However, I did have a branch (in another repo) that uses other different storage, some are purely written in Rust, like "dash" (which is full in-memory), "sled" and "speedb". I eventually decided to stick with RocksDb since its well mature and maintained by some giant companies like Meta.
The user code (the one I wrote) is all Rust.
Also, one could also argue that the `bytes` crate that is heavily utilized in the code base of SableDb, uses plenty of `unsafe` code, does this make it less "Rust" ?
Or do you mean that LSMs shouldn’t be a foundation for a database?