Expand description
kevy-rt — shared-nothing, thread-per-core runtime.
Each core runs its own reactor (kqueue/epoll) and owns one shard of the
keyspace (hash(key) % nshards). There is no shared mutable state and no
lock on the hot path — cores communicate only by message passing over
channels, woken via a self-pipe (kevy_sys::Waker). Connections are spread
across cores by SO_REUSEPORT; a command whose key lives on another core is
forwarded to that core, executed there, and the reply routed back to the
originating connection.
Per-connection reply ordering is preserved (RESP is pipelined): each command gets a monotonic seq; replies are emitted only in contiguous seq order, so an async cross-core reply never overtakes an earlier one.
The cross-core channel currently uses std::sync::mpsc (pure Rust, zero
deps); swapping in a lock-free SPSC/MPSC ring is a perf-polish item.
Command semantics are injected via the Commands trait, keeping the
runtime independent of the concrete command set. Part of the kevy server.
§Module map
Runtime(inruntime) — public entry point; spawns oneshardper core.shard— the per-core reactor: sockets, the inbound queue, reply flushing.exec— command semantics: routing, execution, and result reduction.message— internal cross-core work/result types.conn— per-connection state (input/output, seq ring, subscriptions).reduce— reply reduction (materialize) and pure helpers (set algebra, shard hashing, pub/sub framing).
§Example
Implement Commands for your command set and run it. (Store is
re-exported so you don’t need a separate dependency.)
use kevy_rt::{ArgvView, Commands, Route, Runtime, Store, TxnKind};
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
#[derive(Clone)]
struct MyCommands;
impl Commands for MyCommands {
fn route<A: ArgvView + ?Sized>(&self, args: &A) -> Route {
if args.len() >= 2 { Route::Single(1) } else { Route::Local }
}
fn dispatch<A: ArgvView + ?Sized>(&self, _store: &mut Store, _args: &A) -> Vec<u8> {
b"+OK\r\n".to_vec()
}
fn is_quit<A: ArgvView + ?Sized>(&self, args: &A) -> bool {
args.first().is_some_and(|c| c.eq_ignore_ascii_case(b"QUIT"))
}
fn is_write<A: ArgvView + ?Sized>(&self, _args: &A) -> bool { false }
fn txn_kind<A: ArgvView + ?Sized>(&self, _args: &A) -> TxnKind { TxnKind::Other }
}
// One shard per core, listening on 127.0.0.1:6379, until `stop` is set.
let rt = Runtime::new([127, 0, 0, 1], 6379, 4, MyCommands);
rt.run(Arc::new(AtomicBool::new(false))).unwrap();Structs§
- Argv
- A parsed command’s argument vector.
- Argv
Borrowed - A parsed command’s argument vector that borrows its bytes from a contiguous input buffer.
- Live
Runtime Config - Live snapshot of the runtime-owned knobs that may have been changed
since this shard’s last tick. Built by the
Commandsimpl from its own config source (e.g. kevy readsconfig_global). EachSome(_)is applied to the shard; eachNoneleaves the existing setting alone. - Notification
Flags - Parsed view of
NotificationSection::notify_keyspace_events. The runtime caches this struct per-shard (hot-reload via the existingLiveRuntimeConfigtick path) so the per-write-command check reduces to four bool reads on the hot path. - Replica
Inbox Receiver - Receiver end. Lives inside the (private)
Shard; drained once per reactor tick. Constructed byreplica_inbox_pairand handed to the runtime viaRuntime::with_replica_inboxes. - Replica
Inbox Sender - Sender end of a per-shard replica inbox.
Send + Clone + Sync(one std::sync::mpsc::Sender, no extra state) so the embedder can hand it freely to runner threads. - Replicated
Apply Guard - RAII guard that marks the current thread as “applying a replicated
frame” for the guard’s lifetime. The replica runner (T1.29(b))
enters this scope before each
dispatchcall so the apply doesn’t re-push the frame into this shard’s own backlog. - Resolved
Cmd - Per-command verb-resolution result. Produced once by
Commands::resolvein the reactor’s parse-then-dispatch loop, reused for routing decisions, AOF logging, and the QUIT branch — so the per-cmdupper_verbcost goes from 4× down to 1×. - Runtime
- The public entry point: configure and run the thread-per-core server.
- Store
- A single-database keyspace.
- XGroup
Ctx - The
GROUP <name> <consumer>(+NOACK) context anXREADGROUPgather carries to each per-stream sub-query.
Enums§
- Block
Hint - How a command wants to block, if at all. Returned by
Commands::resolveinsidecrate::ResolvedCmdso the verb-table lookup happens once per command.Noneis the zero-cost default for every non-blocking verb (≥ 99.9 % of dispatches in steady state). - Block
Kind - Which blocking command a waiter is parked in. Drives both timeout-nil shape and wake-retry dispatch.
- Fsync
- When to fsync the AOF to disk.
- Notify
Class - Keyspace-notification event class — what category a write command belongs to, so the runtime can match it against the per-conn notify_keyspace_events flags before publishing.
- Replica
Apply - One event delivered from a replica runner to its target shard.
Mirrors
kevy_replicate::replica::ReplicaEventexceptFramecarries an ownedArgv(already decoded by the runner) instead of aDecodedFrame { offset, argv }— the offset is gap-checked by the runner on the way in, so the shard doesn’t need it. - Resp
Version - Which version of RESP a connection is speaking. Negotiated via the
HELLOcommand — RESP2 is the default for backwards compatibility with every Redis 6.x and earlier client; RESP3 is opt-in viaHELLO 3and unlocks the additive reply types (Reply::Map/Reply::Set/Reply::Double/Reply::Boolean/Reply::Verbatim/Reply::BigNumber/Reply::Null/Reply::Push/Reply::BlobError) plus out-of-band push frames forPUBLISHdelivery. - Route
- How a command maps onto shards.
- Slowlog
Sub - Parsed
SLOWLOG <sub> [args]decision — picked at routing time so the runtime knows whether to fan out or short-circuit. - TxnKind
- Transaction-control classification for a command.
Traits§
- Argv
View - Read-only view over a parsed command’s argument vector.
- Commands
- Command-set semantics injected into the runtime. Cloned to every core, so it must be cheap/stateless to clone.
Functions§
- parse_
slowlog_ sub - Parse
args([verb, sub, ...]) into aSlowlogSub. Verb name is assumed to already be SLOWLOG (the caller’s route table dispatched to here). Embedders call this from theirCommands::resolve/Commands::routeimpl. - replica_
inbox_ pair - Create a matched (sender, receiver) pair for one shard’s replica
inbox. The embedder calls this
nshardstimes beforeRuntime::run. - shard_
slot_ range - The contiguous slot range
[start, end](inclusive, CLUSTER SLOTS shape) shardiofnowns:[ceil(i·16384/n), ceil((i+1)·16384/n) - 1]. Exact inverse ofreduce::slot_to_shard’s multiply-shift.