English | 中文
基于 Rust 构建的分布式键值存储引擎,使用 Raft 共识协议实现数据复制,RocksDB 作为底层存储,gRPC 提供客户端通信。
用 Rust 实现的分布式键值存储,适用于服务发现、配置管理和分布式协调场景,可作为 etcd 的替代方案。
- 单文件部署,无外部依赖 -- 一个二进制文件即可运行,无需 Go 运行时环境
- 无 GC 停顿,延迟稳定 -- 避免了 Go/JVM 存储在高写入压力下的 GC 延迟毛刺
- Gateway 代理模式 -- 读流量增大时可水平扩展 Gateway 节点,不参与 Raft 共识
- 锁、选举、屏障、队列内置 -- etcd 中需要自行组装的协调原语,这里开箱即用
在核心 KV 存储之上,Aether 还提供:
- 事务 -- 通过
TxnRPC 实现 CAS(Compare-and-Swap)操作 - Watch -- 双向流式传输,实时推送键范围变更通知
- 租约 -- 基于 TTL 的键管理,支持自动过期和 Keep-Alive 流
- 分布式锁 -- 互斥锁和读写锁原语
- Leader 选举 -- 基于 Campaign 的选举机制,支持 Observer 流
- 会话管理 -- 客户端会话生命周期管理,支持超时协商
- 屏障与队列 -- 分布式协调原语
- 数据分片 -- 基于 Region 的键范围分片,支持分裂/合并调度
- 集群发现 -- 静态、DNS 和基于 Token 的节点发现,支持动态集群引导
- 认证鉴权 -- JWT 认证 + RBAC 权限(用户、角色、键范围权限)
- 可观测性 -- Prometheus 指标、结构化 JSON 日志、健康检查端点
# 从 Releases 下载二进制文件,然后:
aether --node-id 1 --addr 127.0.0.1:2379为每个节点创建配置文件:
node1.toml
node_id = 1
addr = "127.0.0.1:2379"
data_dir = "/tmp/aether-node1"
[[cluster.peers]]
node_id = 2
addr = "127.0.0.1:2380"
[[cluster.peers]]
node_id = 3
addr = "127.0.0.1:2381"node2.toml
node_id = 2
addr = "127.0.0.1:2380"
data_dir = "/tmp/aether-node2"
[[cluster.peers]]
node_id = 1
addr = "127.0.0.1:2379"
[[cluster.peers]]
node_id = 3
addr = "127.0.0.1:2381"node3.toml
node_id = 3
addr = "127.0.0.1:2381"
data_dir = "/tmp/aether-node3"
[[cluster.peers]]
node_id = 1
addr = "127.0.0.1:2379"
[[cluster.peers]]
node_id = 2
addr = "127.0.0.1:2380"aether --config node1.toml # 终端 1
aether --config node2.toml # 终端 2
aether --config node3.toml # 终端 3无状态代理,将请求路由到后端集群:
aether --gateway --addr 127.0.0.1:2379 \
--backends 127.0.0.1:2380,127.0.0.1:2381,127.0.0.1:2382Aether 默认读取当前目录下的 aether.toml。CLI 参数会覆盖配置文件中的值。
完整配置参考
node_id = 1
addr = "127.0.0.1:2379"
data_dir = "/var/lib/aether"
[cluster]
heartbeat_interval_ms = 1000 # Raft 心跳间隔
election_timeout_ms = 10000 # Raft 选举超时
snapshot_trigger_log_entries = 10000 # 触发快照的日志条目数
[[cluster.peers]]
node_id = 2
addr = "10.0.0.2:2379"
[cluster.discovery]
method = "static" # static, dns, token
[auth]
enabled = false
token_expiry_hours = 24
signing_key = "" # JWT 签名密钥(启用认证时必填)
[lease]
max_leases = 10000
max_ttl = 86400 # 最大租约 TTL(秒)
[log]
level = "info" # trace, debug, info, warn, error
json = false # JSON 结构化日志
log_dir = "" # 为空则仅输出到 stdout
log_file_prefix = "aether"
[metrics]
listen_addr = "127.0.0.1:9090"
[shard]
max_regions = 1024
max_region_size_bytes = 67108864 # 64 MB
auto_split = false所有服务通过同一个 gRPC 地址暴露(默认 127.0.0.1:2379)。
service AetherKV {
rpc Put(PutRequest) returns (PutResponse); // 写入键值对
rpc Get(GetRequest) returns (GetResponse); // 读取单个键或范围
rpc Delete(DeleteRequest) returns (DeleteResponse); // 删除单个键或范围
rpc Range(RangeRequest) returns (RangeResponse); // 范围扫描
rpc Txn(TxnRequest) returns (TxnResponse); // 原子 CAS 事务
}| 服务 | 操作 |
|---|---|
AetherWatch |
Watch(双向流式) |
AetherLease |
LeaseGrant, LeaseRevoke, LeaseKeepAlive, LeaseTimeToLive, LeaseLeases |
AetherAuth |
Authenticate, UserAdd/Delete/Get/List, RoleAdd/Delete/Get/List, UserGrantRole, UserRevokeRole |
AetherCluster |
MemberAdd, MemberRemove, MemberList, MemberPromote |
AetherMaintenance |
Status, AlarmList, AlarmAdd, AlarmDelete, Defragment |
AetherLock |
Lock, Unlock |
AetherElection |
Campaign, Observe, Leader, Resign |
AetherBarrier |
Create, Await |
AetherQueue |
Enqueue, Dequeue |
AetherSession |
Create, Renew, Close |
AetherShard |
CreateRegion, SplitRegion, MergeRegions, GetRegion |
Proto 定义见 proto/。
# Prometheus 指标(与 gRPC 使用相同地址,端口由 metrics.listen_addr 配置)
curl http://127.0.0.1:9090/metrics
# 健康检查(与 metrics 同端口)
curl http://127.0.0.1:9090/health/live # 存活检查
curl http://127.0.0.1:9090/health/ready # 就绪检查(Raft + 存储)运行 cargo bench 可复现。以下为 Apple M 系列芯片的单线程测试结果:
存储引擎(RocksDB)
| 操作 | 延迟 |
|---|---|
| put (256 B) | 1.6 us |
| put (1 KB) | 2.2 us |
| put (64 KB) | 26 us |
| get (命中) | 442 ns |
| get (未命中) | 121 ns |
| delete | 1.4 us |
| batch_write (10 条) | 5.8 us |
| scan (100 键) | 12.9 us |
| scan (1000 键) | 149 us |
Raft 日志存储
| 操作 | 延迟 |
|---|---|
| append_entries (1 条) | 23 us |
| append_entries (10 条) | 48 us |
| append_entries (100 条) | 90 us |
| entries_read (100 条) | 13.3 us |
| entries_read (1000 条) | 140 us |
| save_hard_state | 18.6 us |
| compact (100 条) | 37 us |
docker build -t aether .
docker run -d --name aether-1 \
-p 2379:2379 \
-v aether-data:/data \
aether --node-id 1 --addr 0.0.0.0:2379 --data-dir /data需要 Rust 1.85+(Edition 2024)。
cargo build # Debug 构建
cargo build --release # Release 构建
cargo test # 运行所有测试
cargo clippy -- -D warnings # Lint 检查
cargo fmt -- --check # 格式检查基于 Apache License, Version 2.0 许可。