Key-Value Store SMR Example
This example demonstrates how to build a production-grade distributed key-value store using State Machine Replication (SMR) with the Rabia consensus protocol.
What This Example Shows
The KV Store SMR demonstrates advanced SMR concepts:
- Complex State Management: Managing a dictionary of key-value pairs across replicas
- Change Notifications: Event-driven architecture with publish-subscribe patterns
- Efficient Serialization: Optimized state serialization for large datasets
- Production Features: Comprehensive error handling, monitoring, and observability
State Machine Implementation
The KV store implements these operations:
Set { key, value }- Store a key-value pairGet { key }- Retrieve value for a keyDelete { key }- Remove a key-value pairExists { key }- Check if a key existsListKeys- Get all keys (for debugging/monitoring)Clear- Remove all key-value pairsSize- Get current number of stored keys
Key SMR Features Demonstrated
Complex State Management
Change Notifications (Event-Driven SMR)
// The KV store publishes change notifications
// Clients can subscribe to changes
let subscription_id = store.subscribe_to_changes.await;
Efficient State Snapshots
// Implements efficient serialization for large state
// Supports incremental state updates
async
Architecture Components
Store Layer (store.rs)
High-level interface for KV operations with:
- Connection pooling and load balancing
- Caching and performance optimization
- Metrics collection and monitoring
- Configuration management
Operations Layer (operations.rs)
Defines KV operations and results:
- Operation types and serialization
- Error handling and validation
- Result types and status codes
SMR Implementation (smr_impl.rs)
Core StateMachine trait implementation:
- Deterministic operation application
- State serialization/deserialization
- Change notification generation
Notifications (notifications.rs)
Event-driven change notifications:
- Publication/subscription patterns
- Change event types and routing
- Asynchronous notification delivery
Running the Example
# Run the KV store SMR example
# Run with multiple replicas
# Run tests to see SMR behavior
# Run benchmarks
Use Cases
This pattern is ideal for:
- Configuration Stores: Application configuration management
- Session Storage: User session data across web servers
- Caching: Distributed caching with strong consistency
- Service Discovery: Registry of available services and endpoints
- Feature Flags: Centralized feature flag management
- Metadata Storage: Database metadata, schema information
Advanced Features
Change Notifications
use ;
let mut kvstore = new_with_notifications.await?;
// Subscribe to all changes
let subscription = kvstore.subscribe_to_changes.await;
// Subscribe to specific key patterns
let user_subscription = kvstore.subscribe_to_prefix.await;
// Apply operations and receive notifications
kvstore.set.await?;
// Notification: KeySet { key: "user:123", value: "john_doe", old_value: None }
Batch Operations
use KVOperation;
let batch_ops = vec!;
let results = kvstore.apply_commands.await;
// All operations applied atomically across replicas
State Snapshots and Recovery
// Create snapshot
let snapshot = kvstore.serialize_state;
// Restore from snapshot
let mut new_kvstore = new.await?;
new_kvstore.deserialize_state?;
// Verify restored state
assert_eq!;
Performance Characteristics
Memory Usage
- Efficient HashMap storage with string interning
- Configurable memory limits and eviction policies
- Compressed snapshots for large datasets
Throughput
- Optimized for high-frequency SET/GET operations
- Batch operation support for bulk updates
- Asynchronous notification delivery
Consistency
- Strong consistency across all replicas
- Linearizable read operations
- Atomic batch operations
Configuration Options
use KVStoreConfig;
let config = KVStoreConfig ;
let kvstore = new.await?;
Implementation Notes
Why This Works Well for SMR
- Deterministic Operations: Hash map operations are deterministic and reproducible
- Efficient Serialization: Binary serialization minimizes snapshot overhead
- Event-Driven Architecture: Change notifications enable reactive applications
- Scalable State: Can handle large numbers of keys with efficient memory usage
SMR Considerations
- Memory Usage: Large key-value stores require careful memory management
- Snapshot Frequency: Balance between recovery time and performance overhead
- Notification Ordering: Events are delivered in operation order for consistency
- Error Handling: Robust error handling prevents state machine corruption
Next Steps
After understanding the KV store example, explore:
- Banking SMR - Business logic with complex validation
- Custom State Machine - Template for your own SMR applications
- Performance Benchmarks - SMR performance optimization techniques