Skip to content

angad-singh97/paxos

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Paxos-Based Distributed Transaction System

A fault-tolerant distributed bank — Multi-Paxos consensus over gRPC, catch-up recovery, and concurrent transaction processing. Built from scratch in Java with Spring Boot.

Java Spring Boot gRPC License


What This Is

A distributed transaction processing system that uses a modified Multi-Paxos protocol to achieve consensus across 5 replica servers. When a server has insufficient balance for a transaction, it triggers a Paxos round to reconcile state across the cluster, then applies the agreed-upon transaction block. Includes a catch-up mechanism for lagging nodes and exponential back-off for concurrent proposer conflicts.

Skills demonstrated: Distributed systems · Consensus protocols · gRPC · Protobuf · Concurrent programming · Fault tolerance


What I Built

I implemented the full Paxos consensus pipeline and supporting infrastructure:

  • Modified Prepare/Promise phase — Extended the protocol to detect follower lag, proposer lag, and concurrent ballot clashes. Acceptor logic returns special ballot codes (-10, -20, -30, -40) to signal catch-up needs or back-off.
  • Async Prepare/Accept/Commit — Used CompletableFuture and gRPC deadlines to run consensus phases in parallel across all 5 nodes, with majority quorum (3) and configurable timeouts.
  • Catch-up mechanism — Dedicated worker thread and gRPC service for lagging nodes to fetch missing transaction blocks from a target server and commit them locally before rejoining Paxos.
  • Transaction processing worker — Background ScheduledExecutorService that dequeues transactions and triggers Paxos when balance is insufficient, with retry logic for CatchUpInProgressException, ConcurrentPaxosRoundException, and PaxosMajorityFailedException.
  • Protobuf schema — Defined consensus.proto and catchup.proto for Prepare, Promise, Accept, Commit, and catch-up RPCs.

The BankServer/BankClient scaffolding, gRPC stubs, and basic transaction enqueue flow were provided; I designed and implemented the consensus logic, state machine, and recovery paths.


Architecture

flowchart TB
    subgraph Client["BankClient"]
        TC[TransactionController]
        CSV[CSVTransactionReader]
        TC --> CSV
    end

    subgraph Servers["5 Replica Servers (gRPC)"]
        direction TB
        TS[TransactionService]
        CS[ConsensusService]
        CU[CatchUpService]
    end

    subgraph Consensus["Paxos Pipeline"]
        direction LR
        P[Prepare] --> Pr[Promise]
        Pr --> A[Accept]
        A --> C[Commit]
    end

    subgraph Workers["Background Workers"]
        TW[Transaction Worker]
        CW[CatchUp Worker]
    end

    TC -->|sendTransactionSet| TS
    TS -->|enqueue| TW
    TW -->|insufficient balance| Consensus
    Consensus --> CS
    CW -->|requestCatchUp| CU
    CU -->|blocks| CW
Loading

High-Level Flow

┌─────────────┐     gRPC      ┌──────────────────────────────────────────────────┐
│ BankClient  │ ──────────────▶│ BankServer (×5 replicas)                         │
│ (CSV input) │               │   ├── TransactionService (enqueue)               │
└─────────────┘                │   ├── ConsensusService (Prepare/Accept/Commit)    │
                              │   ├── CatchUpService (sync lagging nodes)         │
                              │   └── Workers: transaction queue, catch-up loop   │
                              └──────────────────────────────────────────────────┘

Features

Component Description
Multi-Paxos consensus Prepare → Promise → Accept → Commit over gRPC with majority quorum
Modified prepare phase Detects follower lag, proposer lag, ballot clash; triggers catch-up or back-off
Catch-up recovery Lagging nodes request missing blocks from target server and commit locally
Async consensus CompletableFuture and gRPC deadlines for parallel Prepare/Accept/Commit
Transaction worker Background worker dequeues transactions; triggers Paxos when balance is low
Exponential back-off Random jitter on retry for concurrent proposer conflicts
5-node cluster Configurable host and ports; server ID derived from port

Highlights

Area Details
Consensus Full Prepare/Promise/Accept/Commit with ballot number, acceptNum, acceptVal, uncommitted T(S)
Failure handling Catch-up for lagging nodes; back-off for concurrent rounds; timeout on majority failure
Concurrency Transaction queue + worker; catch-up worker; async gRPC calls with shared executor
State ConsensusState (ballot, acceptNum, acceptVal, localLog, datastore); Datastore for committed blocks

Project Structure

Path Role
BankServer/src/main/java/.../controller/ConsensusController.java Paxos orchestration: prepare, accept, commit, build MTB
BankServer/src/main/java/.../controller/CatchUpController.java Catch-up worker; sends requests to target server
BankServer/src/main/java/.../service/ConsensusServiceImpl.java Acceptor logic: prepare, accept, commit handlers
BankServer/src/main/java/.../service/CatchUpServiceImpl.java Catch-up responder: returns blocks from datastore
BankServer/src/main/java/.../service/TransactionServiceImpl.java Transaction enqueue, balance, datastore, log
BankServer/src/main/java/.../state/ConsensusState.java Shared state: ballot, acceptNum, acceptVal, queue, flags
BankServer/src/main/java/.../grpc/consensus/ConsensusClient.java gRPC client for Prepare/Accept/Commit
BankServer/src/main/proto/consensus.proto Consensus RPC and message definitions
BankServer/src/main/proto/catchup.proto Catch-up RPC and message definitions
BankClient/ Client app: CSV reader, transaction controller, gRPC clients

Tech Stack

Java 11 · Spring Boot 2.5 · gRPC · Protocol Buffers · Lombok · Maven


Quick Start

Prerequisites: Java 11, Maven

  1. Build and run 5 server replicas (one per host/port):
cd BankServer
mvn clean compile
# Run 5 instances, each with different grpc.server.port (e.g. 9091–9095)
  1. Configure server ports in BankServer/src/main/resources/application.yml:
grpc:
  host: <host-machine>   # e.g. localhost or target platform hostname
  port1: 9091
  port2: 9092
  port3: 9093
  port4: 9094
  port5: 9095
  server:
    port: 9089   # Override per instance
  1. Run the client with a CSV transaction file:
cd BankClient
mvn clean compile exec:java -Dexec.mainClass="org.koatech.bankclient.BankClientApplication"
# Or pass CSV path via your environment / config
  1. CSV format (example): Each row defines a transaction set; columns include live servers and transaction tuples. See BankClient/src/main/resources/transactions.csv for a sample.

Author

Name
Angad Singh · LinkedIn

License

MIT — see LICENSE for details.

About

No description, website, or topics provided.

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages