distributed key-value store with geo-replication
inspired by geohot's minikeyvalue
stores key-value pairs across nodes, eventually consistent (30-50ms), quorum writes (2/3), survives node failures
throughput (single node):
- storage: 2.2M writes/sec, 20M reads/sec
- network: 334k writes/sec, 393k reads/sec (binary tcp)
- http: 100k ops/sec per worker
protocols: binary tcp (performance) + http/json (convenience)
single node:
./minivault -port 3000 -data ./data3-node cluster:
CLUSTER_NODES="localhost:3001,localhost:3002" \
./minivault -port 3001 -data ./data1 -public-url "localhost:3001" &
CLUSTER_NODES="localhost:3000,localhost:3002" \
./minivault -port 3002 -data ./data2 -public-url "localhost:3002" &
CLUSTER_NODES="localhost:3000,localhost:3001" \
./minivault -port 3003 -data ./data3 -public-url "localhost:3003" &docker:
docker-compose up -d # launches 3-node clusternative tcp protocol for performance (tcp:3000 default)
| opcode | name | format | response |
|---|---|---|---|
| 0x01 | GET | [01][keylen:u16][key] |
[status][len:u32][data] |
| 0x02 | SET | [02][keylen:u16][key][vallen:u32][compressed][val] |
[status][len:u32] |
| 0x03 | DELETE | [03][keylen:u16][key] |
[status][len:u32] |
| 0x05 | HEALTH | [05][keylen:u16][key] |
[status][len:u32][json] |
| 0x06 | AUTH | [06][keylen:u16][authkey] |
[status][len:u32] |
response codes:
0x00= success0xFF= error
encoding:
- integers: little-endian
- keylen, vallen: u16, u32
- compressed: 0=no, 1=zstd
optional json-wrapped http interface, enable with -http 8080
endpoints:
PUT /:key- store value (json body:{"value": any})GET /:key- retrieve value (json response:{"success": bool, "data": any})DELETE /:key- remove keyGET /health- cluster status
# set
curl -X PUT http://localhost:8080/mykey \
-H "Content-Type: application/json" \
-d '{"value": "hello world"}'
# get
curl http://localhost:8080/mykey
# {"success":true,"data":"hello world"}
# delete
curl -X DELETE http://localhost:8080/mykey
# health
curl http://localhost:8080/health./minivault -auth "secretkey" -authmode writesmodes:
none- no auth (default)writes- auth required for SET/DELETE (reads public)all- auth required for all ops except health
binary protocol: send OpAuth (0x06) before operations
http protocol: add header Authorization: Bearer secretkey
all clients handle auth automatically when key provided
-port 3000 binary protocol tcp port
-http 0 http json port (0=disabled)
-public-url this node's cluster address (required for multi-node)
-data /data persistent storage directory
-auth "" authentication key
-authmode none auth mode: none|writes|all
-ratelimit 0 ops/sec throttle (0=unlimited)
-cache 512 in-memory cache size (MB)
-workers 50 worker pool size for replication
environment:
CLUSTER_NODES- comma-separated list of other nodes (e.g., "node1:3000,node2:3000")
from source:
# regular build
make build
# optimized build (stripped, smaller binary)
make build-optimized
# run tests
make test
# run benchmarks
make benchdocker:
# build image
make docker-build
# run 3-node cluster
make docker-runprebuilt binaries:
minivault- regular build (9MB)minivault-optimized- stripped symbols (6.2MB)
both binaries included in repo
MIT - see LICENSE file
inspired by geohot's minikeyvalue, rewritten for actual production use