Skip to content

choas/not_redis

 
 

Repository files navigation

not_redis

⚠️ Warning: This project was vibe-coded using OpenCode and MiniMax 2.1 Free. Code was generated by AI and may contain bugs, edge cases, or unexpected behavior. Review thoroughly before production use.


Description

not_redis is a Redis-compatible in-memory data structure library written in Rust. It provides Redis-like APIs without the networking overhead, external service dependencies, or operational complexity of running a Redis server.

Key Goals:

  • Zero-config, embeddable Redis-compatible storage
  • Thread-safe concurrent access via Tokio and DashMap
  • RESP-compatible data types and command semantics
  • No network overhead - runs in-process with your application
  • Minimal dependencies for security and simplicity

Features

  • Strings: GET, SET, DEL, EXISTS, EXPIRE, TTL, PERSIST
  • Hashes: HSET, HGET, HGETALL, HDEL
  • Lists: LPUSH, RPUSH, LLEN
  • Sets: SADD, SMEMBERS
  • Utilities: PING, ECHO, DBSIZE, FLUSHDB

Installation

[dependencies]
not_redis = "0.1"

Getting Started

use not_redis::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut client = Client::new();
    client.start().await;

    // String operations
    client.set("user:1:name", "Alice").await?;
    let name: String = client.get("user:1:name").await?;
    println!("Name: {}", name);

    // Hash operations
    client.hset("user:1", "email", "alice@example.com").await?;
    client.hset("user:1", "age", "30").await?;
    let email: String = client.hget("user:1", "email").await?;
    let profile: Vec<String> = client.hgetall("user:1").await?;
    println!("Email: {}", email);

    // List operations
    client.lpush("user:1:todos", "buy milk").await?;
    client.lpush("user:1:todos", "walk dog").await?;
    let count: i64 = client.llen("user:1:todos").await?;
    println!("Todos: {}", count);

    // Set operations
    client.sadd("user:1:tags", "rust").await?;
    client.sadd("user:1:tags", "developer").await?;
    let tags: Vec<String> = client.smembers("user:1:tags").await?;
    println!("Tags: {:?}", tags);

    // Expiration
    client.set("temp:key", "expires soon").await?;
    client.expire("temp:key", 60).await?;
    let ttl: i64 = client.ttl("temp:key").await?;
    println!("TTL: {} seconds", ttl);

    // Utilities
    let pong: String = client.ping().await?;
    println!("Ping: {}", pong);

    let size: i64 = client.dbsize().await?;
    println!("DB size: {}", size);

    // Cleanup
    let _: String = client.flushdb().await?;

    Ok(())
}

Async Runtime

not_redis requires a Tokio runtime. If you're using it in a non-Tokio context:

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut client = Client::new();
    client.start().await;
    // ... your code ...
}

API Reference

Client

let mut client = Client::new();
client.start().await;
Method Description
get(key) Get value by key
set(key, value) Set key-value pair
del(key) Delete key, returns count
exists(key) Check if key exists
expire(key, seconds) Set key expiration
ttl(key) Get remaining TTL (-2=missing, -1=no expiry, >=0=seconds)
persist(key) Remove expiration, returns success
flushdb() Clear all keys

Hash Operations

Method Description
hset(key, field, value) Set hash field
hget(key, field) Get hash field
hgetall(key) Get all fields/values
hdel(key, field) Delete hash field

List Operations

Method Description
lpush(key, value) Push to list head
rpush(key, value) Push to list tail
llen(key) Get list length

Set Operations

Method Description
sadd(key, member) Add to set
smembers(key) Get all members

Utility Operations

Method Description
ping() Returns "PONG"
echo(msg) Echo message
dbsize() Number of keys

Thread Safety

not_redis uses DashMap for thread-safe concurrent access. Multiple threads can share a single Client instance.

use std::sync::Arc;
use not_redis::Client;

let client = Arc::new(Client::new());
let client_clone = client.clone();

tokio::spawn(async move {
    client_clone.set("key", "value").await.unwrap();
});

Error Handling

use not_redis::{Client, RedisError};

match client.get("nonexistent").await {
    Ok(value) => println!("Found: {}", value),
    Err(RedisError::NoSuchKey(key)) => println!("Key not found: {}", key),
    Err(RedisError::WrongType) => println!("Wrong data type"),
    Err(RedisError::ParseError) => println!("Parse error"),
    Err(e) => println!("Other error: {:?}", e),
}

Why not_redis?

Feature Redis not_redis
Setup Requires Redis server No setup needed
Network TCP/IP overhead In-process, zero-copy
Operations Requires redis-cli or client Direct API calls
Deployment Additional service Single binary

Limitations

  • No persistence (data lost on restart)
  • No networking layer
  • No clustering or replication
  • Limited command set (growing)
  • No Lua scripting
  • No pub/sub

Benchmarks

Benchmarks were run on Apple Silicon (M1) with not_redis and Redis (via redis-rs) to compare performance. Redis was running in a Docker container on the same machine.

Single-Threaded Operations

Operation not_redis Redis Difference
string/set 360,000 ops/s 1,300 ops/s +27,646%
string/get 356,000 ops/s 360 ops/s +98,889%
hash/hset 348,000 ops/s 1,250 ops/s +27,740%
hash/hget 319,000 ops/s 1,400 ops/s +22,771%
list/lpush 358,000 ops/s N/A -
list/rpush 362,000 ops/s N/A -
set/sadd 351,000 ops/s N/A -

Throughput (Batch Operations)

Operation not_redis Redis Difference
batch_writes/100 4.6M ops/s N/A -
batch_writes/1000 5.2M ops/s N/A -
batch_reads/100 3.1M ops/s N/A -
batch_reads/1000 3.3M ops/s N/A -

Why not_redis is Faster

not_redis significantly outperforms Redis for in-process operations because:

  1. Zero network overhead - not_redis runs in the same process, eliminating TCP/IP communication
  2. No serialization/deserialization - Direct memory access vs Redis protocol parsing
  3. No connection management - No connection pooling overhead
  4. Cache-friendly - Data stays in-process, maximizing CPU cache utilization

For applications that don't need Redis's networking capabilities, not_redis provides substantial performance improvements while offering a compatible API.

Contributing

Issues and PRs welcome. Note: This is a vibe-coded project - expect quirks.

License

MIT

About

A Redis-compatible in-memory data structure library for Rust. Provides Redis-like APIs without networking overhead, external dependencies, or operational complexity.

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • Rust 95.5%
  • Shell 4.5%