wedb_embed : Embedded database engine providing Redis-like APIs, built on fjall
- [wedb_embed : Embedded database engine providing Redis-like APIs, built on fjall](#wedb_embed-embedded-database-engine-providing-redis-like-apis-built-on-fjallhttpsgithubcomfjall-rsfjall)
- Motivation
- Core Architecture & Encoding Design
- Usage
- 1. Database Initialization & Configuration (
WeDb&Conf) - 2. Multi-Tenant & Multi-DB Isolation (
Namespace) - 3. Key-Value & String Operations (
KvOps) - 4. Hash Map (
HashOps) - 5. List (
ListOps) - 6. Set (
SetOps) - 7. Sorted Set (
ZSetOps) - 8. Bitmap, Bloom Filter, TimeSeries & Geo (
BitmapOps,BloomOps,TsOps,GeoOps)
- 1. Database Initialization & Configuration (
- Tech Stack
- Benchmark & Performance
Embedded multi-model database engine in Rust, providing Redis-compatible data structures and APIs, built on fjall LSM-Tree for disk-backed persistence.
Motivation
In standalone services and embedded application scenarios, running an external Redis daemon introduces process management overhead and IPC / socket communication round trips.
wedb_embed provides rich Redis-compatible APIs directly as an in-process Rust library:
- In-Process Direct Calls: Eliminates network and IPC latency by reading and writing within the host application process.
- Rich Redis Data Models: Supports String, Hash, List, Set, ZSet, Bitmap, JSON, Bloom/Cuckoo Filter, TimeSeries, Geo, HyperLogLog, TDigest, SortedInt, Stream (all 15 composite types).
- Multi-Tenant & Multi-DB Isolation: Full $2{64}$ tenant and $2{64}$ database capacity with atomic renaming and physical isolation.
- Compact Binary Encoding: Default namespace 0-byte prefix bypass, composite types encoded with 1-Byte
KeyTagand OPPV order-preserving varints. - Disk Persistence & Crash Consistency: Built on fjall LSM-Tree and cross-keyspace atomic write batches for crash-safe operations.
Core Architecture & Encoding Design
graph TD
Client["Application Code"] --> WeDb["WeDb Instance"]
WeDb --> NS["Namespace Handle<br/>(Zero-Heap Struct)"]
subgraph KeyComposer["Key Composer & Fast Encoding"]
Tag["1-Byte Fast KeyTag (#[repr(u8)])"]
OPPV["OPPV Order-Preserving Varint (1~9B)"]
DefaultBypass["Default NS 0-Prefix Bypass"]
Slot["CRC16 Slot & {hashtag}"]
end
subgraph Engine["Storage Engine Layer"]
Batch["Atomic WriteBatch (Cross-Keyspace WAL)"]
Catalog["Catalog Compact Index"]
end
subgraph Storage["Fjall LSM Partitions"]
DataKS["Data Keyspace<br/>(Payloads & Subkeys / 64KB Blocks)"]
MetaKS["Meta Keyspace<br/>(Indices, TTL & Metadata / 4KB Blocks)"]
end
WeDb --> KeyComposer
NS --> KeyComposer
KeyComposer --> Engine
Engine --> DataKS
Engine --> MetaKS
1. Default DB Prefix Optimization & 1-Byte Tag
- Default Namespace: Keys are stored as raw bytes
user_keywith 0-byte prefix overhead. - 1-Byte Fast Tag (
KeyTag): Composite metadata and subkey prefixes use#[repr(u8)] KeyTagencoding (\x00\x01:key), avoiding redundant string prefixes.
2. OPPV Order-Preserving Prefix Varint (oppv_u64)
- Database index and tenant numerical IDs use OPPV (Order-Preserving Prefix Varint) encoding:
- Databases $0 \sim 127$: Encoded in 1 byte.
- Preserves lexicographical byte order equal to numeric value order: $\forall a < b \implies \text{encode}(a) < \text{encode}(b)$.
3. Numerical Tenant ID Mapping & Renaming
- Tenant names map to
ns_id: u64via global metadata. - Tenant Renaming (
rename_namespace): Metadata mapping updated without rewriting underlying data.
4. Streaming Iterators
WeDb::iter(&self) -> Namespaces: Iterates distinct tenants via Jump-Seek.Namespace::iter(&self) -> Dbs: Decodes OPPV catalog entries.
Usage
1. Database Initialization & Configuration (WeDb & Conf)
use ;
2. Multi-Tenant & Multi-DB Isolation (Namespace)
use ;
3. Key-Value & String Operations (KvOps)
use ;
4. Hash Map (HashOps)
use ;
5. List (ListOps)
use ;
6. Set (SetOps)
use ;
7. Sorted Set (ZSetOps)
use ;
8. Bitmap, Bloom Filter, TimeSeries & Geo (BitmapOps, BloomOps, TsOps, GeoOps)
use ;
Tech Stack
- Core Language: Rust Edition 2024
- Storage Engine:
fjall(LSM-Tree Engine) - JSON Engine:
sonic-rs(SIMD JSON Parser) - Hash Algorithm:
rapidhash(Non-Cryptographic Hash) - Serialization:
bitcode(Binary Codec) - Compact String:
hipstr - Time Utilities:
coarsetime,ts_ - Error Handling:
thiserror
Benchmark & Performance
Environment: Ubuntu CI (GitHub Actions Runner)
- CPU:
Intel(R) Xeon(R) 6973P-C (4 Cores) - Memory:
15.6 GB - Platform:
Ubuntu 24.04.4 LTS (Linux 6.17.0-1022-azure) (x86_64) - Compiler:
rustc 1.98.0 (88d9e12ae 2026-08-18)
WeDb (Embedded Engine) vs Redis (v8.10.1 Standalone Server) Performance Comparison
Benchmark Notes:
- WeDb: In-process direct call, LSM disk persistence (WAL journal)
- Redis: Standalone service, AOF persistence enabled (appendfsync everysec), Unix Domain Socket
Composite Performance: WeDb Weighted Throughput 1.689 M ops/s | Redis Weighted Throughput 0.024 M ops/s | WeDb Overall Speedup $\color{#1a7f37}\text{70.1x}$
| Command | WeDb P95 Latency | WeDb Est. Throughput | Redis P95 Latency | Redis Est. Throughput | WeDb Speedup |
|---|---|---|---|---|---|
| SET | 6.009 µs | 1.197 M ops/s | 63.3 µs | 0.021 M ops/s | $\color{#1a7f37}\text{57.7x}$ |
| GET | 267.8 ns | 4.013 M ops/s | 55.29 µs | 0.021 M ops/s | $\color{#1a7f37}\text{192.5x}$ |
| MSET | 12.44 µs | 0.249 M ops/s | 69.21 µs | 0.031 M ops/s | $\color{#1a7f37}\text{8.0x}$ |
| MGET | 3.295 µs | 0.527 M ops/s | 49.88 µs | 0.021 M ops/s | $\color{#1a7f37}\text{25.1x}$ |
| INCRBY | 8.867 µs | 0.987 M ops/s | 79.99 µs | 0.021 M ops/s | $\color{#1a7f37}\text{47.9x}$ |
| HSET | 11.27 µs | 0.663 M ops/s | 55.14 µs | 0.021 M ops/s | $\color{#1a7f37}\text{32.3x}$ |
| HGET | 1.425 µs | 1.767 M ops/s | 63.48 µs | 0.021 M ops/s | $\color{#1a7f37}\text{84.8x}$ |
| LPUSH | 12.19 µs | 0.316 M ops/s | 81.02 µs | 0.020 M ops/s | $\color{#1a7f37}\text{15.5x}$ |
| LPOP | 3.307 µs | 0.509 M ops/s | 51.65 µs | 0.020 M ops/s | $\color{#1a7f37}\text{25.0x}$ |
| SADD | 9.665 µs | 0.682 M ops/s | 69.82 µs | 0.039 M ops/s | $\color{#1a7f37}\text{17.4x}$ |
| SISMEMBER | 579.3 ns | 1.865 M ops/s | 33.42 µs | 0.052 M ops/s | $\color{#1a7f37}\text{35.6x}$ |
| ZADD | 12.26 µs | 0.527 M ops/s | 95.59 µs | 0.021 M ops/s | $\color{#1a7f37}\text{25.2x}$ |
| ZRANGE | 9.29 µs | 0.375 M ops/s | 34.76 µs | 0.043 M ops/s | $\color{#1a7f37}\text{8.8x}$ |
| DEL | 8.569 µs | 0.737 M ops/s | 56.91 µs | 0.021 M ops/s | $\color{#1a7f37}\text{35.9x}$ |
| EXISTS | 3.642 µs | 2.391 M ops/s | 53.85 µs | 0.020 M ops/s | $\color{#1a7f37}\text{117.8x}$ |
Regression Benchmark
Composite Weighted Performance: Weighted Throughput 1.243 M ops/s | Weighted Latency Diff $\color{#0969da}\text{-25%}$
| Command | P95 Latency | Est. Throughput | vs Baseline (%) |
|---|---|---|---|
| BITCOUNT | 2.912 µs | 2.100 M ops/s | $\color{#0969da}\text{-10%}$ |
| BITPOS | 763.5 ns | 3.066 M ops/s | $\color{#1a7f37}\text{+2%}$ |
| GETBIT | 1.908 µs | 2.270 M ops/s | $\color{#0969da}\text{-11%}$ |
| SETBIT | 11.4 µs | 0.657 M ops/s | $\color{#0969da}\text{-41%}$ |
| BF.ADD | 106.3 µs | 0.021 M ops/s | $\color{#0969da}\text{-27%}$ |
| BF.EXISTS | 563.1 ns | 2.372 M ops/s | $\color{#0969da}\text{-19%}$ |
| BF.INFO | 186 ns | 5.659 M ops/s | $\color{#1a7f37}\text{-4%}$ |
| CF.ADD | 21.1 µs | 0.303 M ops/s | $\color{#0969da}\text{-42%}$ |
| CF.DEL | 19.47 µs | 0.159 M ops/s | $\color{#0969da}\text{-35%}$ |
| CF.EXISTS | 665.8 ns | 1.694 M ops/s | $\color{#0969da}\text{-20%}$ |
| BATCH_COMMIT | 9.836 µs | 0.265 M ops/s | $\color{#0969da}\text{-30%}$ |
| DEL | 18.39 µs | 0.507 M ops/s | $\color{#0969da}\text{-48%}$ |
| EXISTS | 2.533 µs | 3.549 M ops/s | $\color{#0969da}\text{-22%}$ |
| NAMESPACE | 7.039 µs | 0.983 M ops/s | $\color{#0969da}\text{-48%}$ |
| GEOADD | 13.16 µs | 0.532 M ops/s | $\color{#0969da}\text{-37%}$ |
| GEODIST | 3.196 µs | 1.977 M ops/s | $\color{#1a7f37}\text{-1%}$ |
| GEOHASH | 1.26 µs | 2.851 M ops/s | $\color{#1a7f37}\text{+1%}$ |
| GEOPOS | 1.728 µs | 3.425 M ops/s | $\color{#1a7f37}\text{+6%}$ |
| HDEL | 35 µs | 0.084 M ops/s | $\color{#0969da}\text{-20%}$ |
| HEXISTS | 420.3 ns | 2.495 M ops/s | $\color{#1a7f37}\text{+2%}$ |
| HGET | 1.56 µs | 1.480 M ops/s | $\color{#0969da}\text{-12%}$ |
| HGETALL | 30.8 µs | 0.044 M ops/s | $\color{#1a7f37}\text{-9%}$ |
| HINCRBY | 10.64 µs | 0.861 M ops/s | $\color{#0969da}\text{-44%}$ |
| HKEYS | 25.58 µs | 0.054 M ops/s | $\color{#0969da}\text{-14%}$ |
| HLEN | 1.96 µs | 3.364 M ops/s | $\color{#0969da}\text{-11%}$ |
| HMGET | 3.538 µs | 0.515 M ops/s | $\color{#1a7f37}\text{-5%}$ |
| HSET | 9.949 µs | 0.613 M ops/s | $\color{#0969da}\text{-41%}$ |
| HVALS | 27.25 µs | 0.054 M ops/s | $\color{#0969da}\text{-24%}$ |
| PFADD | 28.24 µs | 0.129 M ops/s | $\color{#0969da}\text{-41%}$ |
| PFCOUNT | 45.74 µs | 0.036 M ops/s | $\color{#0969da}\text{-20%}$ |
| PFMERGE | 34.24 µs | 0.071 M ops/s | $\color{#0969da}\text{-35%}$ |
| JSON.ARRLEN | 4.744 µs | 2.376 M ops/s | $\color{#0969da}\text{-29%}$ |
| JSON.DEL | 13.38 µs | 0.441 M ops/s | $\color{#0969da}\text{-47%}$ |
| JSON.GET | 5.82 µs | 2.071 M ops/s | $\color{#0969da}\text{-33%}$ |
| JSON.NUMINCRBY | 14.19 µs | 0.756 M ops/s | $\color{#0969da}\text{-48%}$ |
| JSON.SET | 7.076 µs | 0.625 M ops/s | $\color{#0969da}\text{-45%}$ |
| JSON.TYPE | 3.341 µs | 2.795 M ops/s | $\color{#0969da}\text{-29%}$ |
| LINDEX | 1.531 µs | 2.005 M ops/s | $\color{#1a7f37}\text{-3%}$ |
| LLEN | 695.5 ns | 3.602 M ops/s | $\color{#1a7f37}\text{-8%}$ |
| LPOP | 4.442 µs | 0.496 M ops/s | $\color{#0969da}\text{-39%}$ |
| LPUSH | 26.37 µs | 0.733 M ops/s | $\color{#0969da}\text{-43%}$ |
| LRANGE | 36.37 µs | 0.046 M ops/s | $\color{#0969da}\text{-16%}$ |
| LREM | 32.33 µs | 0.086 M ops/s | $\color{#0969da}\text{-19%}$ |
| LSET | 4.271 µs | 0.770 M ops/s | $\color{#0969da}\text{-45%}$ |
| LTRIM | 116.4 µs | 0.010 M ops/s | $\color{#0969da}\text{-42%}$ |
| RPOP | 4.115 µs | 0.515 M ops/s | $\color{#0969da}\text{-39%}$ |
| RPUSH | 10.63 µs | 0.728 M ops/s | $\color{#0969da}\text{-42%}$ |
| SADD | 12.4 µs | 0.647 M ops/s | $\color{#0969da}\text{-42%}$ |
| SCARD | 786 ns | 3.723 M ops/s | $\color{#1a7f37}\text{-10%}$ |
| SISMEMBER | 1.603 µs | 1.558 M ops/s | $\color{#0969da}\text{-16%}$ |
| SMEMBERS | 31.29 µs | 0.053 M ops/s | $\color{#0969da}\text{-16%}$ |
| SPOP | 1.877 ms | 0.001 M ops/s | $\color{#0969da}\text{-15%}$ |
| SRANDMEMBER | 32.24 µs | 0.053 M ops/s | $\color{#0969da}\text{-18%}$ |
| SREM | 24.01 µs | 0.083 M ops/s | $\color{#0969da}\text{-19%}$ |
| SI.ADD | 10.56 µs | 0.672 M ops/s | $\color{#0969da}\text{-41%}$ |
| SI.CARD | 1.556 µs | 3.609 M ops/s | $\color{#1a7f37}\text{-2%}$ |
| SI.EXISTS | 1.658 µs | 1.913 M ops/s | $\color{#1a7f37}\text{-9%}$ |
| SI.RANGE | 17.17 µs | 0.118 M ops/s | $\color{#0969da}\text{-16%}$ |
| SI.REM | 27.07 µs | 0.081 M ops/s | $\color{#0969da}\text{-19%}$ |
| APPEND | 20.18 µs | 0.567 M ops/s | $\color{#0969da}\text{-51%}$ |
| DECRBY | 3.075 µs | 1.141 M ops/s | $\color{#0969da}\text{-53%}$ |
| GET | 1.396 µs | 1.900 M ops/s | $\color{#0969da}\text{-11%}$ |
| GETDEL | 8.726 µs | 0.573 M ops/s | $\color{#0969da}\text{-52%}$ |
| GETRANGE | 190.8 ns | 5.488 M ops/s | $\color{#1a7f37}\text{-6%}$ |
| INCRBY | 8.12 µs | 1.163 M ops/s | $\color{#0969da}\text{-52%}$ |
| MGET | 10.18 µs | 0.523 M ops/s | $\color{#0969da}\text{-13%}$ |
| MSET | 25.02 µs | 0.229 M ops/s | $\color{#0969da}\text{-28%}$ |
| SET | 8.494 µs | 1.239 M ops/s | $\color{#0969da}\text{-53%}$ |
| SETRANGE | 9.97 µs | 0.560 M ops/s | $\color{#0969da}\text{-51%}$ |
| STRLEN | 334.8 ns | 6.112 M ops/s | $\color{#1a7f37}\text{+1%}$ |
| XADD | 21.5 µs | 0.699 M ops/s | $\color{#0969da}\text{-43%}$ |
| XDEL | 28.17 µs | 0.311 M ops/s | $\color{#0969da}\text{-40%}$ |
| XLEN | 212.2 ns | 4.914 M ops/s | $\color{#1a7f37}\text{-5%}$ |
| XRANGE | 22.76 µs | 0.078 M ops/s | $\color{#0969da}\text{-19%}$ |
| XREAD | 21.6 µs | 0.078 M ops/s | $\color{#0969da}\text{-18%}$ |
| TDIGEST.ADD | 6.174 µs | 0.534 M ops/s | $\color{#0969da}\text{-42%}$ |
| TDIGEST.BYRANK | 8.605 µs | 2.104 M ops/s | $\color{#0969da}\text{-32%}$ |
| TDIGEST.CDF | 10.59 µs | 1.067 M ops/s | $\color{#0969da}\text{-30%}$ |
| TDIGEST.QUANTILE | 9.608 µs | 2.562 M ops/s | $\color{#0969da}\text{-31%}$ |
| TS.ADD | 45.21 µs | 0.120 M ops/s | $\color{#0969da}\text{-20%}$ |
| TS.GET | 3.319 µs | 1.648 M ops/s | $\color{#0969da}\text{-23%}$ |
| TS.INCRBY | 42.69 µs | 0.063 M ops/s | $\color{#0969da}\text{-24%}$ |
| TS.RANGE | 52.34 µs | 0.023 M ops/s | $\color{#0969da}\text{-11%}$ |
| ZADD | 16.56 µs | 0.508 M ops/s | $\color{#0969da}\text{-37%}$ |
| ZCARD | 1.098 µs | 6.536 M ops/s | $\color{#1a7f37}\text{-10%}$ |
| ZCOUNT | 77.73 µs | 0.016 M ops/s | $\color{#0969da}\text{-24%}$ |
| ZINCRBY | 13.43 µs | 0.117 M ops/s | $\color{#1a7f37}\text{-9%}$ |
| ZPOPMIN | 28.23 µs | 0.071 M ops/s | $\color{#1a7f37}\text{-7%}$ |
| ZRANGE | 9.684 µs | 0.346 M ops/s | $\color{#0969da}\text{-19%}$ |
| ZRANK | 31.76 µs | 0.094 M ops/s | $\color{#1a7f37}\text{-7%}$ |
| ZREM | 42.02 µs | 0.065 M ops/s | $\color{#1a7f37}\text{+1%}$ |
| ZREVRANGE | 9.264 µs | 0.241 M ops/s | $\color{#0969da}\text{-20%}$ |
| ZSCORE | 590.1 ns | 2.031 M ops/s | $\color{#0969da}\text{-16%}$ |
Environment: macOS (Apple M2 Max)
- CPU:
Apple M2 Max (12 Cores) - Memory:
64.0 GB - Platform:
macOS 26.5.1 (Darwin 25.5.0) (aarch64) - Compiler:
rustc 1.98.0 (88d9e12ae 2026-08-18)
WeDb (Embedded Engine) vs Redis (v8.10.1 Standalone Server) Performance Comparison
Benchmark Notes:
- WeDb: In-process direct call, LSM disk persistence (WAL journal)
- Redis: Standalone service, AOF persistence enabled (appendfsync everysec), Unix Domain Socket
Composite Performance: WeDb Weighted Throughput 0.383 M ops/s | Redis Weighted Throughput 0.012 M ops/s | WeDb Overall Speedup $\color{#1a7f37}\text{31.2x}$
| Command | WeDb P95 Latency | WeDb Est. Throughput | Redis P95 Latency | Redis Est. Throughput | WeDb Speedup |
|---|---|---|---|---|---|
| SET | 29.66 µs | 0.500 M ops/s | 531.2 µs | 0.008 M ops/s | $\color{#1a7f37}\text{61.9x}$ |
| GET | 6.999 µs | 0.632 M ops/s | 76.74 µs | 0.016 M ops/s | $\color{#1a7f37}\text{39.8x}$ |
| MSET | 152.2 µs | 0.052 M ops/s | 561.2 µs | 0.008 M ops/s | $\color{#1a7f37}\text{6.8x}$ |
| MGET | 22.37 µs | 0.286 M ops/s | 328.5 µs | 0.008 M ops/s | $\color{#1a7f37}\text{34.6x}$ |
| INCRBY | 136.6 µs | 0.251 M ops/s | 1.354 ms | 0.005 M ops/s | $\color{#1a7f37}\text{50.0x}$ |
| HSET | 48.29 µs | 0.255 M ops/s | 535.7 µs | 0.009 M ops/s | $\color{#1a7f37}\text{27.9x}$ |
| HGET | 8.04 µs | 0.414 M ops/s | 89.16 µs | 0.016 M ops/s | $\color{#1a7f37}\text{25.6x}$ |
| LPUSH | 141.9 µs | 0.053 M ops/s | 464.4 µs | 0.008 M ops/s | $\color{#1a7f37}\text{6.6x}$ |
| LPOP | 40.24 µs | 0.073 M ops/s | 153.5 µs | 0.014 M ops/s | $\color{#1a7f37}\text{5.0x}$ |
| SADD | 37.58 µs | 0.304 M ops/s | 544.4 µs | 0.009 M ops/s | $\color{#1a7f37}\text{34.2x}$ |
| SISMEMBER | 4.583 µs | 0.775 M ops/s | 85.2 µs | 0.013 M ops/s | $\color{#1a7f37}\text{60.4x}$ |
| ZADD | 52.37 µs | 0.289 M ops/s | 241.8 µs | 0.015 M ops/s | $\color{#1a7f37}\text{19.0x}$ |
| ZRANGE | 33.37 µs | 0.262 M ops/s | 113.1 µs | 0.013 M ops/s | $\color{#1a7f37}\text{20.9x}$ |
| DEL | 16.33 µs | 0.429 M ops/s | 164.2 µs | 0.019 M ops/s | $\color{#1a7f37}\text{22.4x}$ |
| EXISTS | 12.33 µs | 1.171 M ops/s | 50.87 µs | 0.023 M ops/s | $\color{#1a7f37}\text{51.2x}$ |
Regression Benchmark
Composite Weighted Performance: Weighted Throughput 1.292 M ops/s | Weighted Latency Diff $\color{#1a7f37}\text{+12%}$
| Command | P95 Latency | Est. Throughput | vs Baseline (%) |
|---|---|---|---|
| BITCOUNT | 8.083 µs | 2.181 M ops/s | $\color{#cf222e}\text{+22%}$ |
| BITPOS | 397.9 ns | 3.102 M ops/s | $\color{#0969da}\text{-48%}$ |
| GETBIT | 1.187 µs | 1.951 M ops/s | $\color{#cf222e}\text{+32%}$ |
| SETBIT | 79.33 µs | 0.436 M ops/s | $\color{#cf222e}\text{+34%}$ |
| BF.ADD | 433.3 µs | 0.011 M ops/s | $\color{#cf222e}\text{+88%}$ |
| BF.EXISTS | 845.8 ns | 2.261 M ops/s | $\color{#1a7f37}\text{+10%}$ |
| BF.INFO | 340.6 ns | 3.887 M ops/s | $\color{#cf222e}\text{+80%}$ |
| CF.ADD | 65.49 µs | 0.107 M ops/s | $\color{#cf222e}\text{+145%}$ |
| CF.DEL | 67.79 µs | 0.123 M ops/s | $\color{#1a7f37}\text{+13%}$ |
| CF.EXISTS | 869.4 ns | 1.456 M ops/s | $\color{#cf222e}\text{+25%}$ |
| BATCH_COMMIT | 67.24 µs | 0.222 M ops/s | $\color{#cf222e}\text{+20%}$ |
| DEL | 85.12 µs | 0.304 M ops/s | $\color{#1a7f37}\text{+8%}$ |
| EXISTS | 5.666 µs | 2.999 M ops/s | $\color{#1a7f37}\text{-0%}$ |
| NAMESPACE | 69.91 µs | 0.522 M ops/s | $\color{#cf222e}\text{+35%}$ |
| GEOADD | 77.12 µs | 0.421 M ops/s | $\color{#1a7f37}\text{+12%}$ |
| GEODIST | 559.4 ns | 2.222 M ops/s | $\color{#cf222e}\text{+16%}$ |
| GEOHASH | 413.6 ns | 2.766 M ops/s | $\color{#0969da}\text{-57%}$ |
| GEOPOS | 366.7 ns | 3.344 M ops/s | $\color{#cf222e}\text{+25%}$ |
| HDEL | 80.33 µs | 0.100 M ops/s | $\color{#1a7f37}\text{+8%}$ |
| HEXISTS | 411 ns | 2.936 M ops/s | $\color{#1a7f37}\text{-3%}$ |
| HGET | 817.2 ns | 1.392 M ops/s | $\color{#1a7f37}\text{+15%}$ |
| HGETALL | 37.58 µs | 0.076 M ops/s | $\color{#1a7f37}\text{-8%}$ |
| HINCRBY | 68.16 µs | 0.649 M ops/s | $\color{#1a7f37}\text{-5%}$ |
| HKEYS | 20.74 µs | 0.080 M ops/s | $\color{#1a7f37}\text{+8%}$ |
| HLEN | 317.2 ns | 3.967 M ops/s | $\color{#1a7f37}\text{-7%}$ |
| HMGET | 10.79 µs | 0.471 M ops/s | $\color{#1a7f37}\text{+15%}$ |
| HSET | 56.91 µs | 0.453 M ops/s | $\color{#1a7f37}\text{0%}$ |
| HVALS | 22.16 µs | 0.074 M ops/s | $\color{#0969da}\text{-11%}$ |
| PFADD | 68.2 µs | 0.097 M ops/s | $\color{#cf222e}\text{+16%}$ |
| PFCOUNT | 41.79 µs | 0.030 M ops/s | $\color{#1a7f37}\text{-8%}$ |
| PFMERGE | 51.37 µs | 0.059 M ops/s | $\color{#1a7f37}\text{+2%}$ |
| JSON.ARRLEN | 17.91 µs | 0.924 M ops/s | $\color{#cf222e}\text{+100%}$ |
| JSON.DEL | 93.7 µs | 0.267 M ops/s | $\color{#1a7f37}\text{+5%}$ |
| JSON.GET | 15.66 µs | 1.503 M ops/s | $\color{#cf222e}\text{+23%}$ |
| JSON.NUMINCRBY | 17.79 µs | 0.558 M ops/s | $\color{#1a7f37}\text{0%}$ |
| JSON.SET | 56.29 µs | 0.407 M ops/s | $\color{#cf222e}\text{+20%}$ |
| JSON.TYPE | 5.208 µs | 2.002 M ops/s | $\color{#cf222e}\text{+20%}$ |
| LINDEX | 533.3 ns | 2.302 M ops/s | $\color{#1a7f37}\text{+8%}$ |
| LLEN | 237.8 ns | 4.398 M ops/s | $\color{#1a7f37}\text{+13%}$ |
| LPOP | 6.457 µs | 0.429 M ops/s | $\color{#1a7f37}\text{-3%}$ |
| LPUSH | 55.37 µs | 0.632 M ops/s | $\color{#1a7f37}\text{-0%}$ |
| LRANGE | 31.2 µs | 0.043 M ops/s | $\color{#cf222e}\text{+22%}$ |
| LREM | 129.3 µs | 0.109 M ops/s | $\color{#1a7f37}\text{+2%}$ |
| LSET | 4.541 µs | 0.546 M ops/s | $\color{#cf222e}\text{+300%}$ |
| LTRIM | 194.2 µs | 0.007 M ops/s | $\color{#1a7f37}\text{+4%}$ |
| RPOP | 5.29 µs | 0.471 M ops/s | $\color{#1a7f37}\text{+2%}$ |
| RPUSH | 75.45 µs | 0.522 M ops/s | $\color{#0969da}\text{-51%}$ |
| SADD | 76.66 µs | 0.453 M ops/s | $\color{#cf222e}\text{+20%}$ |
| SCARD | 353.7 ns | 3.434 M ops/s | $\color{#cf222e}\text{+29%}$ |
| SISMEMBER | 666.2 ns | 1.657 M ops/s | $\color{#0969da}\text{-15%}$ |
| SMEMBERS | 20.83 µs | 0.084 M ops/s | $\color{#1a7f37}\text{-0%}$ |
| SPOP | 1.262 ms | 0.001 M ops/s | $\color{#1a7f37}\text{-0%}$ |
| SRANDMEMBER | 115.5 µs | 0.078 M ops/s | $\color{#1a7f37}\text{+8%}$ |
| SREM | 121.5 µs | 0.111 M ops/s | $\color{#1a7f37}\text{-1%}$ |
| SI.ADD | 142.5 µs | 0.534 M ops/s | $\color{#1a7f37}\text{+12%}$ |
| SI.CARD | 236.5 ns | 5.621 M ops/s | $\color{#1a7f37}\text{+1%}$ |
| SI.EXISTS | 647.9 ns | 2.095 M ops/s | $\color{#1a7f37}\text{-3%}$ |
| SI.RANGE | 15.91 µs | 0.182 M ops/s | $\color{#1a7f37}\text{-3%}$ |
| SI.REM | 91.49 µs | 0.101 M ops/s | $\color{#1a7f37}\text{+8%}$ |
| APPEND | 88.83 µs | 0.400 M ops/s | $\color{#0969da}\text{-56%}$ |
| DECRBY | 62.74 µs | 0.858 M ops/s | $\color{#1a7f37}\text{-10%}$ |
| GET | 666.1 ns | 2.344 M ops/s | $\color{#1a7f37}\text{+6%}$ |
| GETDEL | 442.2 µs | 0.173 M ops/s | $\color{#cf222e}\text{+128%}$ |
| GETRANGE | 114.1 ns | 9.891 M ops/s | $\color{#1a7f37}\text{+4%}$ |
| INCRBY | 97.58 µs | 0.829 M ops/s | $\color{#1a7f37}\text{-3%}$ |
| MGET | 4.874 µs | 0.600 M ops/s | $\color{#1a7f37}\text{+11%}$ |
| MSET | 139.3 µs | 0.202 M ops/s | $\color{#1a7f37}\text{+15%}$ |
| SET | 116.7 µs | 0.751 M ops/s | $\color{#1a7f37}\text{+14%}$ |
| SETRANGE | 158.5 µs | 0.358 M ops/s | $\color{#0969da}\text{-51%}$ |
| STRLEN | 96.56 ns | 11.972 M ops/s | $\color{#1a7f37}\text{-1%}$ |
| XADD | 49.99 µs | 0.572 M ops/s | $\color{#1a7f37}\text{+2%}$ |
| XDEL | 55.87 µs | 0.229 M ops/s | $\color{#cf222e}\text{+23%}$ |
| XLEN | 163.6 ns | 6.262 M ops/s | $\color{#1a7f37}\text{+12%}$ |
| XRANGE | 34.04 µs | 0.091 M ops/s | $\color{#1a7f37}\text{+9%}$ |
| XREAD | 28.37 µs | 0.086 M ops/s | $\color{#1a7f37}\text{+12%}$ |
| TDIGEST.ADD | 17.54 µs | 0.308 M ops/s | $\color{#1a7f37}\text{+7%}$ |
| TDIGEST.BYRANK | 11.83 µs | 1.413 M ops/s | $\color{#1a7f37}\text{+13%}$ |
| TDIGEST.CDF | 17.91 µs | 0.961 M ops/s | $\color{#cf222e}\text{+19%}$ |
| TDIGEST.QUANTILE | 16.08 µs | 1.847 M ops/s | $\color{#1a7f37}\text{-7%}$ |
| TS.ADD | 165 µs | 0.142 M ops/s | $\color{#1a7f37}\text{+1%}$ |
| TS.GET | 697.5 ns | 1.763 M ops/s | $\color{#1a7f37}\text{+7%}$ |
| TS.INCRBY | 27.2 µs | 0.069 M ops/s | $\color{#1a7f37}\text{+7%}$ |
| TS.RANGE | 28.58 µs | 0.038 M ops/s | $\color{#1a7f37}\text{+13%}$ |
| ZADD | 141.1 µs | 0.381 M ops/s | $\color{#cf222e}\text{+19%}$ |
| ZCARD | 174 ns | 7.485 M ops/s | $\color{#cf222e}\text{+24%}$ |
| ZCOUNT | 60.24 µs | 0.021 M ops/s | $\color{#cf222e}\text{+21%}$ |
| ZINCRBY | 106.8 µs | 0.125 M ops/s | $\color{#cf222e}\text{+22%}$ |
| ZPOPMIN | 14.83 µs | 0.109 M ops/s | $\color{#1a7f37}\text{+7%}$ |
| ZRANGE | 11.29 µs | 0.375 M ops/s | $\color{#cf222e}\text{+20%}$ |
| ZRANK | 10.29 µs | 0.155 M ops/s | $\color{#1a7f37}\text{+5%}$ |
| ZREM | 172.6 µs | 0.113 M ops/s | $\color{#1a7f37}\text{+3%}$ |
| ZREVRANGE | 12.49 µs | 0.253 M ops/s | $\color{#1a7f37}\text{+10%}$ |
| ZSCORE | 765.1 ns | 1.568 M ops/s | $\color{#cf222e}\text{+29%}$ |
wedb_embed : 嵌入式数据库引擎,提供类似 Redis 的接口,底层基于 fjall 开发
- [wedb_embed : 嵌入式数据库引擎,提供类似 Redis 的接口,底层基于 fjall 开发](#wedb_embed-嵌入式数据库引擎提供类似-redis-的接口底层基于-fjallhttpsgithubcomfjall-rsfjall-开发)
基于 Rust 开发的嵌入式多模型数据库引擎,提供与 Redis 兼容的数据结构与操作接口,底层采用 fjall LSM-Tree 进行磁盘持久化存储。
项目初衷
在许多单机服务或嵌入式应用场景中,部署和维护独立的 Redis 守护进程会增加运维复杂度,并且跨进程通信(IPC / Socket 网络与 RESP 编解码)会带来额外的延迟开销。 在单机或嵌入式应用中,部署独立 Redis 进程会增加运维复杂度,且跨进程通信(IPC/Socket 与 RESP 编解码)会引入额外延迟。
wedb_embed 作为 Rust 原生库嵌入应用程序:
- 进程内调用:无网络与 IPC 开销,直接在内存与磁盘间进行读写。
- 丰富的数据模型:支持 String、Hash、List、Set、ZSet、Bitmap、JSON、Bloom/Cuckoo Filter、TimeSeries、Geo、HyperLogLog、TDigest、SortedInt、Stream 等 15 种数据结构。
- 多租户与分库隔离:原生支持 $2{64}$ 租户与 $2{64}$ 分库,具备原子改名与物理隔离能力。
- 紧凑二进制编码:默认库采用 0 字节前缀,复合结构使用 1-Byte
KeyTag与 OPPV 变长保序编码。 - 持久化一致性:基于 fjall LSM-Tree 存储引擎与跨 Keyspace 原子 WriteBatch,保障数据安全。
核心架构与编码设计
graph TD
Client["Application Code"] --> WeDb["WeDb Instance"]
WeDb --> NS["Namespace Handle<br/>(Zero-Heap Struct)"]
subgraph KeyComposer["Key Composer & Fast Encoding"]
Tag["1-Byte Fast KeyTag (#[repr(u8)])"]
OPPV["OPPV Order-Preserving Varint (1~9B)"]
DefaultBypass["Default NS 0-Prefix Bypass"]
Slot["CRC16 Slot & {hashtag}"]
end
subgraph Engine["Storage Engine Layer"]
Batch["Atomic WriteBatch (Cross-Keyspace WAL)"]
Catalog["Catalog Compact Index"]
end
subgraph Storage["Fjall LSM Partitions"]
DataKS["Data Keyspace<br/>(业务载荷与子键 / 64KB 块)"]
MetaKS["Meta Keyspace<br/>(常驻索引、TTL 与元数据 / 4KB 块)"]
end
WeDb --> KeyComposer
NS --> KeyComposer
KeyComposer --> Engine
Engine --> DataKS
Engine --> MetaKS
1. 默认库前缀优化与 1-Byte 标签
- 默认命名空间:键直接为原始字节
user_key,物理前缀占用 0 字节。 - 1-Byte Fast Tag (
KeyTag):复合结构元数据与子键前缀采用#[repr(u8)] KeyTag编码(\x00\x01:key等),消除冗余字符串标签。
2. OPPV 保序变长整型编码 (oppv_u64)
- 数据库编号与租户数字 ID 采用 OPPV(Order-Preserving Prefix Varint) 编码:
- 分库 $0 \sim 127$:占用 1 字节(相比固定 8 字节大端序节约空间)。
- 全范围保持字节字典序与数值顺序等价:$\forall a < b \implies \text{encode}(a) < \text{encode}(b)$。
3. 多租户数字 ID 映射与重命名
- 租户名称与
ns_id: u64采用全局元数据原子映射。 - 租户改名 (
rename_namespace):更新元数据映射即可完成重命名,无需重写底层业务键。
4. 流式迭代器
WeDb::iter(&self) -> Namespaces:基于字典序跳跃二分(Prefix Jump-Seek)定位租户。Namespace::iter(&self) -> Dbs:直接流式解包底层 OPPV 变长 Catalog 目录。
使用演示
1. 数据库打开与配置 (WeDb & Conf)
use ;
2. 多租户与分库隔离 (Namespace)
use ;
3. 键值与字符串 (KvOps)
use ;
4. 哈希字典 (HashOps)
use ;
5. 列表 (ListOps)
use ;
6. 集合 (SetOps)
use ;
7. 有序集合 (ZSetOps)
use ;
8. 位图、布隆过滤、时序与地理位置 (BitmapOps, BloomOps, TsOps, GeoOps)
use ;
技术堆栈
- 核心语言:Rust Edition 2024
- 底层存储:
fjall(LSM-Tree 持久化引擎) - JSON 解析:
sonic-rs(SIMD 指令集加速 JSON 引擎) - 哈希算法:
rapidhash(非加密哈希算法) - 二进制编解码:
bitcode(二进制序列化) - 字符串存储:
hipstr(紧凑字符串存储) - 时间库:
coarsetime、ts_(时间戳) - 错误定义:
thiserror
性能基准与回归测试
运行环境:Ubuntu CI (GitHub Actions Runner)
- CPU:
Intel(R) Xeon(R) 6973P-C (4 核) - 内存:
15.6 GB - 系统:
Ubuntu 24.04.4 LTS (Linux 6.17.0-1022-azure) (x86_64) - 编译器:
rustc 1.98.0 (88d9e12ae 2026-08-18)
WeDb (嵌入式引擎) vs Redis (v8.10.1 独立服务) 性能对比
测试说明:
- WeDb:进程内直接调用,基于 LSM 磁盘持久化(WAL 日志)
- Redis:独立服务,开启 AOF 持久化(appendfsync everysec),通过本地 Unix Domain Socket 通信
综合性能对比:WeDb 加权吞吐量 168.915 万次/秒 | Redis 加权吞吐量 2.408 万次/秒 | WeDb 综合性能倍数 $\color{#1a7f37}\text{70.1x}$
| 命令 | WeDb P95延时 | WeDb 估算吞吐量 | Redis P95延时 | Redis 估算吞吐量 | WeDb 性能倍数 |
|---|---|---|---|---|---|
| SET | 6.009 µs | 119.717 万次/秒 | 63.3 µs | 2.074 万次/秒 | $\color{#1a7f37}\text{57.7x}$ |
| GET | 267.8 ns | 401.284 万次/秒 | 55.29 µs | 2.084 万次/秒 | $\color{#1a7f37}\text{192.5x}$ |
| MSET | 12.44 µs | 24.857 万次/秒 | 69.21 µs | 3.122 万次/秒 | $\color{#1a7f37}\text{8.0x}$ |
| MGET | 3.295 µs | 52.743 万次/秒 | 49.88 µs | 2.103 万次/秒 | $\color{#1a7f37}\text{25.1x}$ |
| INCRBY | 8.867 µs | 98.717 万次/秒 | 79.99 µs | 2.063 万次/秒 | $\color{#1a7f37}\text{47.9x}$ |
| HSET | 11.27 µs | 66.313 万次/秒 | 55.14 µs | 2.053 万次/秒 | $\color{#1a7f37}\text{32.3x}$ |
| HGET | 1.425 µs | 176.741 万次/秒 | 63.48 µs | 2.085 万次/秒 | $\color{#1a7f37}\text{84.8x}$ |
| LPUSH | 12.19 µs | 31.586 万次/秒 | 81.02 µs | 2.037 万次/秒 | $\color{#1a7f37}\text{15.5x}$ |
| LPOP | 3.307 µs | 50.942 万次/秒 | 51.65 µs | 2.035 万次/秒 | $\color{#1a7f37}\text{25.0x}$ |
| SADD | 9.665 µs | 68.166 万次/秒 | 69.82 µs | 3.917 万次/秒 | $\color{#1a7f37}\text{17.4x}$ |
| SISMEMBER | 579.3 ns | 186.463 万次/秒 | 33.42 µs | 5.244 万次/秒 | $\color{#1a7f37}\text{35.6x}$ |
| ZADD | 12.26 µs | 52.715 万次/秒 | 95.59 µs | 2.094 万次/秒 | $\color{#1a7f37}\text{25.2x}$ |
| ZRANGE | 9.29 µs | 37.495 万次/秒 | 34.76 µs | 4.279 万次/秒 | $\color{#1a7f37}\text{8.8x}$ |
| DEL | 8.569 µs | 73.746 万次/秒 | 56.91 µs | 2.053 万次/秒 | $\color{#1a7f37}\text{35.9x}$ |
| EXISTS | 3.642 µs | 239.063 万次/秒 | 53.85 µs | 2.029 万次/秒 | $\color{#1a7f37}\text{117.8x}$ |
性能回归测试
综合加权性能:加权估算吞吐量 124.290 万次/秒 | 加权延迟变动 $\color{#0969da}\text{-25%}$
| 命令 | P95延时 | 估算吞吐量 | 较基线变化 (%) |
|---|---|---|---|
| BITCOUNT | 2.912 µs | 210.040 万次/秒 | $\color{#0969da}\text{-10%}$ |
| BITPOS | 763.5 ns | 306.560 万次/秒 | $\color{#1a7f37}\text{+2%}$ |
| GETBIT | 1.908 µs | 226.963 万次/秒 | $\color{#0969da}\text{-11%}$ |
| SETBIT | 11.4 µs | 65.703 万次/秒 | $\color{#0969da}\text{-41%}$ |
| BF.ADD | 106.3 µs | 2.080 万次/秒 | $\color{#0969da}\text{-27%}$ |
| BF.EXISTS | 563.1 ns | 237.192 万次/秒 | $\color{#0969da}\text{-19%}$ |
| BF.INFO | 186 ns | 565.931 万次/秒 | $\color{#1a7f37}\text{-4%}$ |
| CF.ADD | 21.1 µs | 30.285 万次/秒 | $\color{#0969da}\text{-42%}$ |
| CF.DEL | 19.47 µs | 15.941 万次/秒 | $\color{#0969da}\text{-35%}$ |
| CF.EXISTS | 665.8 ns | 169.405 万次/秒 | $\color{#0969da}\text{-20%}$ |
| BATCH_COMMIT | 9.836 µs | 26.476 万次/秒 | $\color{#0969da}\text{-30%}$ |
| DEL | 18.39 µs | 50.736 万次/秒 | $\color{#0969da}\text{-48%}$ |
| EXISTS | 2.533 µs | 354.862 万次/秒 | $\color{#0969da}\text{-22%}$ |
| NAMESPACE | 7.039 µs | 98.328 万次/秒 | $\color{#0969da}\text{-48%}$ |
| GEOADD | 13.16 µs | 53.248 万次/秒 | $\color{#0969da}\text{-37%}$ |
| GEODIST | 3.196 µs | 197.707 万次/秒 | $\color{#1a7f37}\text{-1%}$ |
| GEOHASH | 1.26 µs | 285.144 万次/秒 | $\color{#1a7f37}\text{+1%}$ |
| GEOPOS | 1.728 µs | 342.466 万次/秒 | $\color{#1a7f37}\text{+6%}$ |
| HDEL | 35 µs | 8.389 万次/秒 | $\color{#0969da}\text{-20%}$ |
| HEXISTS | 420.3 ns | 249.501 万次/秒 | $\color{#1a7f37}\text{+2%}$ |
| HGET | 1.56 µs | 147.973 万次/秒 | $\color{#0969da}\text{-12%}$ |
| HGETALL | 30.8 µs | 4.442 万次/秒 | $\color{#1a7f37}\text{-9%}$ |
| HINCRBY | 10.64 µs | 86.059 万次/秒 | $\color{#0969da}\text{-44%}$ |
| HKEYS | 25.58 µs | 5.397 万次/秒 | $\color{#0969da}\text{-14%}$ |
| HLEN | 1.96 µs | 336.361 万次/秒 | $\color{#0969da}\text{-11%}$ |
| HMGET | 3.538 µs | 51.546 万次/秒 | $\color{#1a7f37}\text{-5%}$ |
| HSET | 9.949 µs | 61.312 万次/秒 | $\color{#0969da}\text{-41%}$ |
| HVALS | 27.25 µs | 5.382 万次/秒 | $\color{#0969da}\text{-24%}$ |
| PFADD | 28.24 µs | 12.857 万次/秒 | $\color{#0969da}\text{-41%}$ |
| PFCOUNT | 45.74 µs | 3.602 万次/秒 | $\color{#0969da}\text{-20%}$ |
| PFMERGE | 34.24 µs | 7.123 万次/秒 | $\color{#0969da}\text{-35%}$ |
| JSON.ARRLEN | 4.744 µs | 237.643 万次/秒 | $\color{#0969da}\text{-29%}$ |
| JSON.DEL | 13.38 µs | 44.053 万次/秒 | $\color{#0969da}\text{-47%}$ |
| JSON.GET | 5.82 µs | 207.125 万次/秒 | $\color{#0969da}\text{-33%}$ |
| JSON.NUMINCRBY | 14.19 µs | 75.643 万次/秒 | $\color{#0969da}\text{-48%}$ |
| JSON.SET | 7.076 µs | 62.539 万次/秒 | $\color{#0969da}\text{-45%}$ |
| JSON.TYPE | 3.341 µs | 279.486 万次/秒 | $\color{#0969da}\text{-29%}$ |
| LINDEX | 1.531 µs | 200.481 万次/秒 | $\color{#1a7f37}\text{-3%}$ |
| LLEN | 695.5 ns | 360.231 万次/秒 | $\color{#1a7f37}\text{-8%}$ |
| LPOP | 4.442 µs | 49.579 万次/秒 | $\color{#0969da}\text{-39%}$ |
| LPUSH | 26.37 µs | 73.260 万次/秒 | $\color{#0969da}\text{-43%}$ |
| LRANGE | 36.37 µs | 4.587 万次/秒 | $\color{#0969da}\text{-16%}$ |
| LREM | 32.33 µs | 8.628 万次/秒 | $\color{#0969da}\text{-19%}$ |
| LSET | 4.271 µs | 77.042 万次/秒 | $\color{#0969da}\text{-45%}$ |
| LTRIM | 116.4 µs | 0.983 万次/秒 | $\color{#0969da}\text{-42%}$ |
| RPOP | 4.115 µs | 51.520 万次/秒 | $\color{#0969da}\text{-39%}$ |
| RPUSH | 10.63 µs | 72.780 万次/秒 | $\color{#0969da}\text{-42%}$ |
| SADD | 12.4 µs | 64.725 万次/秒 | $\color{#0969da}\text{-42%}$ |
| SCARD | 786 ns | 372.301 万次/秒 | $\color{#1a7f37}\text{-10%}$ |
| SISMEMBER | 1.603 µs | 155.812 万次/秒 | $\color{#0969da}\text{-16%}$ |
| SMEMBERS | 31.29 µs | 5.288 万次/秒 | $\color{#0969da}\text{-16%}$ |
| SPOP | 1.877 ms | 0.055 万次/秒 | $\color{#0969da}\text{-15%}$ |
| SRANDMEMBER | 32.24 µs | 5.294 万次/秒 | $\color{#0969da}\text{-18%}$ |
| SREM | 24.01 µs | 8.340 万次/秒 | $\color{#0969da}\text{-19%}$ |
| SI.ADD | 10.56 µs | 67.159 万次/秒 | $\color{#0969da}\text{-41%}$ |
| SI.CARD | 1.556 µs | 360.881 万次/秒 | $\color{#1a7f37}\text{-2%}$ |
| SI.EXISTS | 1.658 µs | 191.278 万次/秒 | $\color{#1a7f37}\text{-9%}$ |
| SI.RANGE | 17.17 µs | 11.806 万次/秒 | $\color{#0969da}\text{-16%}$ |
| SI.REM | 27.07 µs | 8.110 万次/秒 | $\color{#0969da}\text{-19%}$ |
| APPEND | 20.18 µs | 56.689 万次/秒 | $\color{#0969da}\text{-51%}$ |
| DECRBY | 3.075 µs | 114.116 万次/秒 | $\color{#0969da}\text{-53%}$ |
| GET | 1.396 µs | 190.006 万次/秒 | $\color{#0969da}\text{-11%}$ |
| GETDEL | 8.726 µs | 57.339 万次/秒 | $\color{#0969da}\text{-52%}$ |
| GETRANGE | 190.8 ns | 548.847 万次/秒 | $\color{#1a7f37}\text{-6%}$ |
| INCRBY | 8.12 µs | 116.306 万次/秒 | $\color{#0969da}\text{-52%}$ |
| MGET | 10.18 µs | 52.274 万次/秒 | $\color{#0969da}\text{-13%}$ |
| MSET | 25.02 µs | 22.925 万次/秒 | $\color{#0969da}\text{-28%}$ |
| SET | 8.494 µs | 123.870 万次/秒 | $\color{#0969da}\text{-53%}$ |
| SETRANGE | 9.97 µs | 55.991 万次/秒 | $\color{#0969da}\text{-51%}$ |
| STRLEN | 334.8 ns | 611.247 万次/秒 | $\color{#1a7f37}\text{+1%}$ |
| XADD | 21.5 µs | 69.930 万次/秒 | $\color{#0969da}\text{-43%}$ |
| XDEL | 28.17 µs | 31.066 万次/秒 | $\color{#0969da}\text{-40%}$ |
| XLEN | 212.2 ns | 491.400 万次/秒 | $\color{#1a7f37}\text{-5%}$ |
| XRANGE | 22.76 µs | 7.770 万次/秒 | $\color{#0969da}\text{-19%}$ |
| XREAD | 21.6 µs | 7.770 万次/秒 | $\color{#0969da}\text{-18%}$ |
| TDIGEST.ADD | 6.174 µs | 53.362 万次/秒 | $\color{#0969da}\text{-42%}$ |
| TDIGEST.BYRANK | 8.605 µs | 210.393 万次/秒 | $\color{#0969da}\text{-32%}$ |
| TDIGEST.CDF | 10.59 µs | 106.689 万次/秒 | $\color{#0969da}\text{-30%}$ |
| TDIGEST.QUANTILE | 9.608 µs | 256.213 万次/秒 | $\color{#0969da}\text{-31%}$ |
| TS.ADD | 45.21 µs | 11.967 万次/秒 | $\color{#0969da}\text{-20%}$ |
| TS.GET | 3.319 µs | 164.799 万次/秒 | $\color{#0969da}\text{-23%}$ |
| TS.INCRBY | 42.69 µs | 6.349 万次/秒 | $\color{#0969da}\text{-24%}$ |
| TS.RANGE | 52.34 µs | 2.300 万次/秒 | $\color{#0969da}\text{-11%}$ |
| ZADD | 16.56 µs | 50.813 万次/秒 | $\color{#0969da}\text{-37%}$ |
| ZCARD | 1.098 µs | 653.595 万次/秒 | $\color{#1a7f37}\text{-10%}$ |
| ZCOUNT | 77.73 µs | 1.563 万次/秒 | $\color{#0969da}\text{-24%}$ |
| ZINCRBY | 13.43 µs | 11.692 万次/秒 | $\color{#1a7f37}\text{-9%}$ |
| ZPOPMIN | 28.23 µs | 7.082 万次/秒 | $\color{#1a7f37}\text{-7%}$ |
| ZRANGE | 9.684 µs | 34.590 万次/秒 | $\color{#0969da}\text{-19%}$ |
| ZRANK | 31.76 µs | 9.390 万次/秒 | $\color{#1a7f37}\text{-7%}$ |
| ZREM | 42.02 µs | 6.464 万次/秒 | $\color{#1a7f37}\text{+1%}$ |
| ZREVRANGE | 9.264 µs | 24.096 万次/秒 | $\color{#0969da}\text{-20%}$ |
| ZSCORE | 590.1 ns | 203.128 万次/秒 | $\color{#0969da}\text{-16%}$ |
运行环境:macOS (Apple M2 Max)
- CPU:
Apple M2 Max (12 核) - 内存:
64.0 GB - 系统:
macOS 26.5.1 (Darwin 25.5.0) (aarch64) - 编译器:
rustc 1.98.0 (88d9e12ae 2026-08-18)
WeDb (嵌入式引擎) vs Redis (v8.10.1 独立服务) 性能对比
测试说明:
- WeDb:进程内直接调用,基于 LSM 磁盘持久化(WAL 日志)
- Redis:独立服务,开启 AOF 持久化(appendfsync everysec),通过本地 Unix Domain Socket 通信
综合性能对比:WeDb 加权吞吐量 38.314 万次/秒 | Redis 加权吞吐量 1.228 万次/秒 | WeDb 综合性能倍数 $\color{#1a7f37}\text{31.2x}$
| 命令 | WeDb P95延时 | WeDb 估算吞吐量 | Redis P95延时 | Redis 估算吞吐量 | WeDb 性能倍数 |
|---|---|---|---|---|---|
| SET | 29.66 µs | 50.025 万次/秒 | 531.2 µs | 0.808 万次/秒 | $\color{#1a7f37}\text{61.9x}$ |
| GET | 6.999 µs | 63.211 万次/秒 | 76.74 µs | 1.587 万次/秒 | $\color{#1a7f37}\text{39.8x}$ |
| MSET | 152.2 µs | 5.247 万次/秒 | 561.2 µs | 0.770 万次/秒 | $\color{#1a7f37}\text{6.8x}$ |
| MGET | 22.37 µs | 28.580 万次/秒 | 328.5 µs | 0.825 万次/秒 | $\color{#1a7f37}\text{34.6x}$ |
| INCRBY | 136.6 µs | 25.138 万次/秒 | 1.354 ms | 0.503 万次/秒 | $\color{#1a7f37}\text{50.0x}$ |
| HSET | 48.29 µs | 25.536 万次/秒 | 535.7 µs | 0.915 万次/秒 | $\color{#1a7f37}\text{27.9x}$ |
| HGET | 8.04 µs | 41.391 万次/秒 | 89.16 µs | 1.614 万次/秒 | $\color{#1a7f37}\text{25.6x}$ |
| LPUSH | 141.9 µs | 5.299 万次/秒 | 464.4 µs | 0.800 万次/秒 | $\color{#1a7f37}\text{6.6x}$ |
| LPOP | 40.24 µs | 7.262 万次/秒 | 153.5 µs | 1.446 万次/秒 | $\color{#1a7f37}\text{5.0x}$ |
| SADD | 37.58 µs | 30.386 万次/秒 | 544.4 µs | 0.888 万次/秒 | $\color{#1a7f37}\text{34.2x}$ |
| SISMEMBER | 4.583 µs | 77.519 万次/秒 | 85.2 µs | 1.284 万次/秒 | $\color{#1a7f37}\text{60.4x}$ |
| ZADD | 52.37 µs | 28.927 万次/秒 | 241.8 µs | 1.519 万次/秒 | $\color{#1a7f37}\text{19.0x}$ |
| ZRANGE | 33.37 µs | 26.233 万次/秒 | 113.1 µs | 1.256 万次/秒 | $\color{#1a7f37}\text{20.9x}$ |
| DEL | 16.33 µs | 42.882 万次/秒 | 164.2 µs | 1.916 万次/秒 | $\color{#1a7f37}\text{22.4x}$ |
| EXISTS | 12.33 µs | 117.069 万次/秒 | 50.87 µs | 2.287 万次/秒 | $\color{#1a7f37}\text{51.2x}$ |
性能回归测试
综合加权性能:加权估算吞吐量 129.193 万次/秒 | 加权延迟变动 $\color{#1a7f37}\text{+12%}$
| 命令 | P95延时 | 估算吞吐量 | 较基线变化 (%) |
|---|---|---|---|
| BITCOUNT | 8.083 µs | 218.103 万次/秒 | $\color{#cf222e}\text{+22%}$ |
| BITPOS | 397.9 ns | 310.174 万次/秒 | $\color{#0969da}\text{-48%}$ |
| GETBIT | 1.187 µs | 195.122 万次/秒 | $\color{#cf222e}\text{+32%}$ |
| SETBIT | 79.33 µs | 43.649 万次/秒 | $\color{#cf222e}\text{+34%}$ |
| BF.ADD | 433.3 µs | 1.130 万次/秒 | $\color{#cf222e}\text{+88%}$ |
| BF.EXISTS | 845.8 ns | 226.142 万次/秒 | $\color{#1a7f37}\text{+10%}$ |
| BF.INFO | 340.6 ns | 388.651 万次/秒 | $\color{#cf222e}\text{+80%}$ |
| CF.ADD | 65.49 µs | 10.668 万次/秒 | $\color{#cf222e}\text{+145%}$ |
| CF.DEL | 67.79 µs | 12.309 万次/秒 | $\color{#1a7f37}\text{+13%}$ |
| CF.EXISTS | 869.4 ns | 145.560 万次/秒 | $\color{#cf222e}\text{+25%}$ |
| BATCH_COMMIT | 67.24 µs | 22.227 万次/秒 | $\color{#cf222e}\text{+20%}$ |
| DEL | 85.12 µs | 30.386 万次/秒 | $\color{#1a7f37}\text{+8%}$ |
| EXISTS | 5.666 µs | 299.850 万次/秒 | $\color{#1a7f37}\text{-0%}$ |
| NAMESPACE | 69.91 µs | 52.192 万次/秒 | $\color{#cf222e}\text{+35%}$ |
| GEOADD | 77.12 µs | 42.123 万次/秒 | $\color{#1a7f37}\text{+12%}$ |
| GEODIST | 559.4 ns | 222.222 万次/秒 | $\color{#cf222e}\text{+16%}$ |
| GEOHASH | 413.6 ns | 276.625 万次/秒 | $\color{#0969da}\text{-57%}$ |
| GEOPOS | 366.7 ns | 334.448 万次/秒 | $\color{#cf222e}\text{+25%}$ |
| HDEL | 80.33 µs | 10.022 万次/秒 | $\color{#1a7f37}\text{+8%}$ |
| HEXISTS | 411 ns | 293.600 万次/秒 | $\color{#1a7f37}\text{-3%}$ |
| HGET | 817.2 ns | 139.237 万次/秒 | $\color{#1a7f37}\text{+15%}$ |
| HGETALL | 37.58 µs | 7.553 万次/秒 | $\color{#1a7f37}\text{-8%}$ |
| HINCRBY | 68.16 µs | 64.893 万次/秒 | $\color{#1a7f37}\text{-5%}$ |
| HKEYS | 20.74 µs | 8.006 万次/秒 | $\color{#1a7f37}\text{+8%}$ |
| HLEN | 317.2 ns | 396.668 万次/秒 | $\color{#1a7f37}\text{-7%}$ |
| HMGET | 10.79 µs | 47.081 万次/秒 | $\color{#1a7f37}\text{+15%}$ |
| HSET | 56.91 µs | 45.310 万次/秒 | $\color{#1a7f37}\text{0%}$ |
| HVALS | 22.16 µs | 7.435 万次/秒 | $\color{#0969da}\text{-11%}$ |
| PFADD | 68.2 µs | 9.718 万次/秒 | $\color{#cf222e}\text{+16%}$ |
| PFCOUNT | 41.79 µs | 2.978 万次/秒 | $\color{#1a7f37}\text{-8%}$ |
| PFMERGE | 51.37 µs | 5.921 万次/秒 | $\color{#1a7f37}\text{+2%}$ |
| JSON.ARRLEN | 17.91 µs | 92.421 万次/秒 | $\color{#cf222e}\text{+100%}$ |
| JSON.DEL | 93.7 µs | 26.674 万次/秒 | $\color{#1a7f37}\text{+5%}$ |
| JSON.GET | 15.66 µs | 150.263 万次/秒 | $\color{#cf222e}\text{+23%}$ |
| JSON.NUMINCRBY | 17.79 µs | 55.835 万次/秒 | $\color{#1a7f37}\text{0%}$ |
| JSON.SET | 56.29 µs | 40.683 万次/秒 | $\color{#cf222e}\text{+20%}$ |
| JSON.TYPE | 5.208 µs | 200.200 万次/秒 | $\color{#cf222e}\text{+20%}$ |
| LINDEX | 533.3 ns | 230.203 万次/秒 | $\color{#1a7f37}\text{+8%}$ |
| LLEN | 237.8 ns | 439.754 万次/秒 | $\color{#1a7f37}\text{+13%}$ |
| LPOP | 6.457 µs | 42.863 万次/秒 | $\color{#1a7f37}\text{-3%}$ |
| LPUSH | 55.37 µs | 63.211 万次/秒 | $\color{#1a7f37}\text{-0%}$ |
| LRANGE | 31.2 µs | 4.318 万次/秒 | $\color{#cf222e}\text{+22%}$ |
| LREM | 129.3 µs | 10.910 万次/秒 | $\color{#1a7f37}\text{+2%}$ |
| LSET | 4.541 µs | 54.585 万次/秒 | $\color{#cf222e}\text{+300%}$ |
| LTRIM | 194.2 µs | 0.706 万次/秒 | $\color{#1a7f37}\text{+4%}$ |
| RPOP | 5.29 µs | 47.081 万次/秒 | $\color{#1a7f37}\text{+2%}$ |
| RPUSH | 75.45 µs | 52.219 万次/秒 | $\color{#0969da}\text{-51%}$ |
| SADD | 76.66 µs | 45.310 万次/秒 | $\color{#cf222e}\text{+20%}$ |
| SCARD | 353.7 ns | 343.407 万次/秒 | $\color{#cf222e}\text{+29%}$ |
| SISMEMBER | 666.2 ns | 165.673 万次/秒 | $\color{#0969da}\text{-15%}$ |
| SMEMBERS | 20.83 µs | 8.368 万次/秒 | $\color{#1a7f37}\text{-0%}$ |
| SPOP | 1.262 ms | 0.093 万次/秒 | $\color{#1a7f37}\text{-0%}$ |
| SRANDMEMBER | 115.5 µs | 7.794 万次/秒 | $\color{#1a7f37}\text{+8%}$ |
| SREM | 121.5 µs | 11.112 万次/秒 | $\color{#1a7f37}\text{-1%}$ |
| SI.ADD | 142.5 µs | 53.362 万次/秒 | $\color{#1a7f37}\text{+12%}$ |
| SI.CARD | 236.5 ns | 562.114 万次/秒 | $\color{#1a7f37}\text{+1%}$ |
| SI.EXISTS | 647.9 ns | 209.512 万次/秒 | $\color{#1a7f37}\text{-3%}$ |
| SI.RANGE | 15.91 µs | 18.185 万次/秒 | $\color{#1a7f37}\text{-3%}$ |
| SI.REM | 91.49 µs | 10.106 万次/秒 | $\color{#1a7f37}\text{+8%}$ |
| APPEND | 88.83 µs | 40.016 万次/秒 | $\color{#0969da}\text{-56%}$ |
| DECRBY | 62.74 µs | 85.763 万次/秒 | $\color{#1a7f37}\text{-10%}$ |
| GET | 666.1 ns | 234.412 万次/秒 | $\color{#1a7f37}\text{+6%}$ |
| GETDEL | 442.2 µs | 17.268 万次/秒 | $\color{#cf222e}\text{+128%}$ |
| GETRANGE | 114.1 ns | 989.120 万次/秒 | $\color{#1a7f37}\text{+4%}$ |
| INCRBY | 97.58 µs | 82.850 万次/秒 | $\color{#1a7f37}\text{-3%}$ |
| MGET | 4.874 µs | 60.024 万次/秒 | $\color{#1a7f37}\text{+11%}$ |
| MSET | 139.3 µs | 20.169 万次/秒 | $\color{#1a7f37}\text{+15%}$ |
| SET | 116.7 µs | 75.075 万次/秒 | $\color{#1a7f37}\text{+14%}$ |
| SETRANGE | 158.5 µs | 35.829 万次/秒 | $\color{#0969da}\text{-51%}$ |
| STRLEN | 96.56 ns | 1197.175 万次/秒 | $\color{#1a7f37}\text{-1%}$ |
| XADD | 49.99 µs | 57.176 万次/秒 | $\color{#1a7f37}\text{+2%}$ |
| XDEL | 55.87 µs | 22.862 万次/秒 | $\color{#cf222e}\text{+23%}$ |
| XLEN | 163.6 ns | 626.174 万次/秒 | $\color{#1a7f37}\text{+12%}$ |
| XRANGE | 34.04 µs | 9.099 万次/秒 | $\color{#1a7f37}\text{+9%}$ |
| XREAD | 28.37 µs | 8.636 万次/秒 | $\color{#1a7f37}\text{+12%}$ |
| TDIGEST.ADD | 17.54 µs | 30.779 万次/秒 | $\color{#1a7f37}\text{+7%}$ |
| TDIGEST.BYRANK | 11.83 µs | 141.343 万次/秒 | $\color{#1a7f37}\text{+13%}$ |
| TDIGEST.CDF | 17.91 µs | 96.061 万次/秒 | $\color{#cf222e}\text{+19%}$ |
| TDIGEST.QUANTILE | 16.08 µs | 184.672 万次/秒 | $\color{#1a7f37}\text{-7%}$ |
| TS.ADD | 165 µs | 14.203 万次/秒 | $\color{#1a7f37}\text{+1%}$ |
| TS.GET | 697.5 ns | 176.305 万次/秒 | $\color{#1a7f37}\text{+7%}$ |
| TS.INCRBY | 27.2 µs | 6.878 万次/秒 | $\color{#1a7f37}\text{+7%}$ |
| TS.RANGE | 28.58 µs | 3.804 万次/秒 | $\color{#1a7f37}\text{+13%}$ |
| ZADD | 141.1 µs | 38.110 万次/秒 | $\color{#cf222e}\text{+19%}$ |
| ZCARD | 174 ns | 748.503 万次/秒 | $\color{#cf222e}\text{+24%}$ |
| ZCOUNT | 60.24 µs | 2.077 万次/秒 | $\color{#cf222e}\text{+21%}$ |
| ZINCRBY | 106.8 µs | 12.534 万次/秒 | $\color{#cf222e}\text{+22%}$ |
| ZPOPMIN | 14.83 µs | 10.885 万次/秒 | $\color{#1a7f37}\text{+7%}$ |
| ZRANGE | 11.29 µs | 37.523 万次/秒 | $\color{#cf222e}\text{+20%}$ |
| ZRANK | 10.29 µs | 15.535 万次/秒 | $\color{#1a7f37}\text{+5%}$ |
| ZREM | 172.6 µs | 11.348 万次/秒 | $\color{#1a7f37}\text{+3%}$ |
| ZREVRANGE | 12.49 µs | 25.265 万次/秒 | $\color{#1a7f37}\text{+10%}$ |
| ZSCORE | 765.1 ns | 156.838 万次/秒 | $\color{#cf222e}\text{+29%}$ |