Skip to content

fanaujie/babuza

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

165 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Babuza

Languages: English | 繁體中文

Babuza turns etcd Raft into an embeddable Go framework for production services. It provides the Raft runtime, WAL, snapshots, transport, sessions, cluster operations, and integration test harness you otherwise have to build around etcd/raft yourself.

Why Babuza?

Building distributed systems with Raft is hard. While etcd provides a battle-tested Raft implementation, using it directly requires significant effort:

  • Raft Ready Loop: You must implement a goroutine to process Ready() structs, handle entries, messages, snapshots, and hard state persistence in the correct order
  • Storage Integration: WAL and snapshot storage must be carefully coordinated - write entries before sending messages, apply snapshots atomically
  • Network Layer: Build your own transport to send/receive Raft messages between peers, handle connection failures and retries
  • State Machine Lifecycle: Manage snapshot creation, restoration, and log compaction while ensuring consistency
  • Cluster Membership: Implement protocol for adding/removing nodes, handling joint consensus, and learner promotion
Challenge etcd Raft Babuza
Memory Management Keeps all log entries in memory Index-based caching saves 94-99% memory
Network Transport Basic HTTP transport provided Pluggable TCP/HTTP/gRPC transports
WAL etcd WAL provided Multiple backends: native, Badger, Pebble
Snapshot Transfer Full transfer via HTTP Compressed & chunked transfer with rate limiting
Cluster Operations Manual peer management Built-in add/remove/transfer APIs
Idempotency Application handles dedup Session-based exactly-once semantics
Observability Roll your own Prometheus & OpenTelemetry built-in
Disaster Recovery Complex manual process One-command standalone restoration
Integration Testing Write your own test harness testcluster with fault injection & partition simulation

Babuza lets you focus on your application logic, not Raft plumbing.

Core Features

Feature What Babuza Provides
Raft Runtime Ready-loop processing, proposal handling, linearizable reads, and lifecycle management
WAL Backends Native Babuza WAL, etcd WAL, Badger, and Pebble options
Snapshot Management Durable, volatile, and S3-compatible snapshot storage with chunked transfer
Transport Layer Pluggable TCP, HTTP, and gRPC transports, including HTTP stream mode
Client Sessions Optional exactly-once semantics through no-op, expiring, or LRU session managers
Cluster Operations Add/remove/update peers, promote learners, transfer leadership, and disaster recovery
Testing Harness Multi-node testcluster support with partitions, node failures, restarts, and fault injection
Observability Prometheus and OpenTelemetry integration points

Performance

Memory Efficiency

Entries Data Size etcd Memory Babuza Memory Saved
100K 1 KB 102 MB 5.35 MB 94.8%
100K 10 KB 981 MB 5.35 MB 99.5%

Babuza stores log entry metadata in memory and reads entry payloads from WAL on demand, so memory usage stays mostly independent of entry data size. See the full Memory Usage Benchmark Report.

HTTP Stream Transport

HTTP transport supports an opt-in stream mode that reuses long-lived HTTP request bodies for framed Raft messages and snapshot chunks. In local benchmarks, stream mode significantly reduces per-message request overhead:

Workload Short Request HTTP Stream Improvement
Batch message 26.806 us/op 2.349 us/op 11.4x faster
Snapshot, 32 x 256 B chunks 990.327 us/op 148.066 us/op 6.7x faster
Snapshot, 4 x 8 KiB chunks 175.458 us/op 90.616 us/op 1.9x faster

See the full HTTP Stream Benchmark Comparison for benchmark details and allocation results.

Architecture

architecture

Quick Start

package main

import (
	"context"
	"encoding/json"
	"fmt"
	"sync"
	"time"

	"github.com/fanaujie/babuza/ibabuza"
	"github.com/fanaujie/babuza/raft"
)

// 1. Implement your state machine
type KVStore struct {
	mu   sync.RWMutex
	data map[string]string
}

func (s *KVStore) Apply(e ibabuza.Entry) ibabuza.ApplyResult {
	var cmd struct{ Key, Value string }
	json.Unmarshal(e.Command, &cmd)
	s.mu.Lock()
	s.data[cmd.Key] = cmd.Value
	s.mu.Unlock()
	return ibabuza.ApplyResult{LogIndex: e.Index}
}
func (s *KVStore) Query(key any) (any, error) {
	s.mu.RLock()
	defer s.mu.RUnlock()
	return s.data[key.(string)], nil
}
func (s *KVStore) SaveSnapshot(ibabuza.StateMachineSnapshotContext, ibabuza.StateMachineSnapshotWriter) error { return nil }
func (s *KVStore) RestoreFromSnapshot(ibabuza.StateMachineSnapshotReader) error { return nil }
func (s *KVStore) Close() error { return nil }

func main() {
	// 2. Start Raft with default settings
	r, _ := raft.NewDefaultBuilder().
		DataDir("/tmp/babuza").
		StateMachine(&KVStore{data: make(map[string]string)}).
		Start()

	// 3. Wait for leader election
	time.Sleep(2 * time.Second)

	// 4. Propose data through Raft consensus
	data, _ := json.Marshal(map[string]string{"Key": "hello", "Value": "world"})
	r.Propose(context.Background(), raft.ClientSession{}, data).WaitForApplyResult()

	fmt.Println("Data committed through Raft consensus!")
	r.Shutdown().Wait()
}

Examples

Example Description
Simple Minimal single-node Raft example
KV Store Single-raft distributed key-value store with REST API
Distributed Lock Lease-based distributed lock with fencing tokens and wait queue
Redis Cluster Multi-raft Redis-compatible distributed cache

AI-Assisted Development

Use babuza-skills to enhance AI coding assistants (Claude Code, Cursor, Aider) with Babuza-specific knowledge for code generation and explanations.

Documentation

Core Packages

Package Description
ibabuza Core interfaces for all pluggable components
raft Consensus layer, cluster bootstrap, and Raft API
pkg/builder Component builder pattern for easy assembly

Infrastructure Packages

Package Description
pkg/cluster Cluster membership and peer management
pkg/transport Network transport layer (TCP, HTTP, gRPC)
pkg/session Client session management for idempotency
pkg/snapshot Snapshot creation, storage, and restoration
pkg/wal Write-ahead log implementations

Configuration

Component Types

Component Available Types
Session noop, expire, lru
Transport tcp, tcp-memory, http, grpc
WAL babuza-wal, etcd-wal, badger-wal, badger-wal-memory, pebble-wal, pebble-wal-memory
Snapshot durable, volatile, s3
Metrics otel, prometheus

Experimental Multi-Raft

The raft/experimental package implements multi-Raft group support without modifying the upstream etcd Raft library:

  • Coalesced Heartbeats - Merge heartbeats from multiple Raft groups to reduce network overhead
  • Shared WAL - Multiple Raft groups share a single WAL instance
  • Sharded Scheduling - Efficient processing across many Raft groups

Test Cluster Framework

Babuza provides a testcluster framework for testing distributed system failure scenarios:

Supported Failure Scenarios:

Scenario Description
Node Disconnect Simulate single node network failure
Network Partition Split cluster into isolated groups
Leader Failure Stop/restart leader node
Quorum Loss Disconnect majority of nodes
Node Restart Stop and restart with WAL/snapshot recovery
Disaster Recovery Recover standalone from lost cluster

Contributing

Contributions are welcome! Please ensure:

  1. Tests are included for new functionality
  2. Documentation is updated as needed

License

Apache License 2.0. See LICENSE for details.

Copyright 2025 Chen Chunchieh

About

A Go framework built on etcd Raft for building distributed consensus-based systems with simplified APIs and some features.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages