Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

High-Performance Java Matching Engine

A deterministic, event-driven matching engine built with Java 17, Spring Boot, Apache Kafka, MySQL, and LMAX Disruptor.

The project demonstrates how a trading order book can process commands through a single-writer state machine, publish settlement events, and recover safely from database snapshots and Kafka replay.

Highlights

  • Limit orders, market orders, and cancellations
  • Price-time priority using in-memory order books
  • Single-writer processing without locks in the matching path
  • LMAX Disruptor ring buffer between Kafka ingestion and matching
  • BigDecimal for financial calculations and serialization
  • Partitioned settlement events for downstream processing
  • Snapshot persistence with safe Kafka offset recovery
  • Duplicate-input and duplicate-output protection
  • Docker Compose environment for MySQL and Kafka

Architecture

flowchart LR
    O["Kafka: offer.eth_btc"] --> C["OfferConsumer"]
    C --> D["LMAX Disruptor"]
    D --> H["Single Match Event Handler"]
    H --> E["Matching Engine"]
    E --> B["In-memory Order Book"]
    E --> S["Kafka: settle.0-63"]
    E --> Q["Kafka: quote_deals.eth_btc"]
    H --> P["Consistent Snapshot Copy"]
    P --> M["MySQL Snapshot Storage"]
Loading

The matching state is owned by one event-handler thread. Kafka callbacks only publish commands to the ring buffer; they never mutate the order book directly.

Consistency Model

The engine stores the last safely processed Kafka offset in each snapshot. On restart it restores the order book and seeks to the next offset. Duplicate commands and already-published output IDs are ignored.

offer.eth_btc intentionally uses exactly one Kafka partition. A single ordered command stream is required because the current engine maintains one global market state and one input offset. The consumer fails fast if this invariant is violated.

Snapshot creation is initiated by a sentinel event in the same ring buffer. This ensures all earlier commands have completed before the in-memory state is copied. Database I/O then runs on a separate worker so it does not block matching.

See ARCH_OVERVIEW.md for detailed sequence diagrams.

Technology

  • Java 17
  • Spring Boot 3.2
  • Spring Kafka
  • LMAX Disruptor 4
  • Spring Data JPA and JDBC
  • MySQL 8
  • JUnit 5 and Mockito
  • Docker Compose

Run Locally

Requirements:

  • JDK 17+
  • Maven 3.9+
  • Docker with Docker Compose

Start MySQL, Kafka, and the required topics:

cd docker
docker compose up -d

Then start the engine from the project root:

mvn spring-boot:run

The default local configuration uses:

Setting Default Environment variable
MySQL URL jdbc:mysql://localhost:3306/matchengine DB_URL
MySQL user user DB_USERNAME
MySQL password password DB_PASSWORD
Kafka brokers localhost:9092 KAFKA_BOOTSTRAP_SERVERS
HTTP port 8080 SERVER_PORT

Defaults are intended only for the local Docker environment. Use secrets or environment variables outside local development.

Example Command

Publish a limit-order command to offer.eth_btc:

{
  "id": 1001,
  "method": "order.put_limit",
  "params": {
    "user_id": 42,
    "side": 1,
    "amount": "1.5000",
    "price": "2500.0000",
    "taker_fee_rate": "0.0010",
    "maker_fee_rate": "0.0010"
  }
}

The order book can be inspected at:

GET http://localhost:8080/api/market/orderbook

Tests

Run the unit test suite with:

mvn test

The tests cover price priority, time priority, partial fills, market-buy quote consumption, cancellations, minimum order size, per-user open-order limits, safe snapshot metadata recovery, and the single-partition input invariant.

Microbenchmarks

The project includes JMH benchmarks for the isolated in-memory matching core:

mvn -Pbenchmark clean compile exec:exec

Latest local measurement:

Operation Average time
Insert a passive limit order 119.170 ns/op
Match one limit order immediately 231.439 ns/op

These are microbenchmark results, not end-to-end system latency. Kafka, JSON parsing, database snapshots, logging, networking, and settlement delivery are intentionally excluded. See BENCHMARKS.md for the environment, methodology, uncertainty, and reproduction details.

Scope

This repository is a focused reference implementation for a single market. A production deployment would additionally require authentication, authorization, schema validation, metrics, tracing, dead-letter handling, multi-market orchestration, integration tests, and end-to-end load and latency testing.

License

This project is available under the MIT License.

About

Event-driven Java matching engine built with Spring Boot, Kafka, MySQL and LMAX Disruptor.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages