Отметим: когда клиент говорит «у нас latency на matching 200 мс» — мы сразу знаем: проблема в архитектуре order book. В нашей практике был случай: биржа теряла до 10% ордеров из-за блокировок на уровне БД. Решение — in-memory order book с минимальной синхронизацией. Мы разрабатываем высокопроизводительные order book под ключ для crypto-бирж. Наш опыт — 15+ проектов.
Order book — центральный компонент любой биржи. Это упорядоченный список заявок на покупку и продажу актива. Производительность order book напрямую определяет возможности всей торговой системы: от latency исполнения до максимального throughput. Поддерживаются лимитные и рыночные ордера. Средняя экономия на инфраструктурных затратах после внедрения in-memory решения достигает 40% при нагрузке 50 000+ ордеров в секунду.
Как устроен in-memory order book?
Order book живёт в оперативной памяти. Доступ к диску при каждом matching — неприемлемо по latency. Классическая структура: два отсортированных контейнера — bid side (покупки, по убыванию цены) и ask side (продажи, по возрастанию цены). На каждом ценовом уровне — очередь ордеров (FIFO для price-time priority).
type Order struct { ID string UserID int64 Side Side // Buy | Sell Type OrderType // Limit | Market Price decimal.Decimal Quantity decimal.Decimal FilledQty decimal.Decimal CreatedAt int64 // nanosecond timestamp } type PriceLevel struct { Price decimal.Decimal Orders []*Order // FIFO queue } type OrderBook struct { Bids *redblacktree.Tree // Price -> *PriceLevel, descending Asks *redblacktree.Tree // Price -> *PriceLevel, ascending Orders map[string]*Order // OrderID -> Order (для быстрой отмены) mu sync.RWMutex } Выбор tree-структуры:
- Red-black tree: O(log n) для всех операций. Библиотека emirpasic/gods — хорошая Go реализация.
- Skip list: конкурентный, но сложнее. Lock-free skip list даёт лучшую масштабируемость для многоядерных систем.
- Sorted slice + binary search: O(n) insert, O(log n) search. Работает для небольших books (< 1000 уровней).
Почему отмена ордера должна быть O(1)?
Если отмена ордера требует поиска по всем уровням, latency растёт линейно. Мы используем hashmap Orders map[string]*Order — прямая индексация по ID. Это критично для high-frequency trading, где каждая микросекунда на счету.
Matching алгоритм: FIFO vs Pro-Rata
Price-Time Priority (FIFO) — стандарт для большинства бирж. FIFO до 2 раз быстрее Pro-Rata при высокой нагрузке, но Pro-Rata стимулирует крупные заявки. Мы выбираем алгоритм под ваши задачи.
func (ob *OrderBook) matchOrder(taker *Order) []Trade { var trades []Trade counterSide := ob.getCounterBook(taker.Side) for taker.RemainingQty().IsPositive() { bestLevel := ob.getBestLevel(counterSide) if bestLevel == nil { break } if !ob.priceCrosses(taker, bestLevel.Price) { break } for len(bestLevel.Orders) > 0 && taker.RemainingQty().IsPositive() { maker := bestLevel.Orders[0] fillQty := decimal.Min(taker.RemainingQty(), maker.RemainingQty()) trades = append(trades, Trade{ Price: bestLevel.Price, Quantity: fillQty, TakerOrderID: taker.ID, MakerOrderID: maker.ID, TakerSide: taker.Side, Timestamp: time.Now().UnixNano(), }) taker.FilledQty = taker.FilledQty.Add(fillQty) maker.FilledQty = maker.FilledQty.Add(fillQty) if maker.RemainingQty().IsZero() { bestLevel.Orders = bestLevel.Orders[1:] delete(ob.Orders, maker.ID) } } if len(bestLevel.Orders) == 0 { ob.removeLevel(counterSide, bestLevel.Price) } } return trades } Снэпшот и инкрементальные обновления
Клиент не получает весь order book при подключении — это может быть мегабайты. Архитектура:
- Клиент запрашивает снэпшот (top N уровней, например 50) через REST.
- Подписывается на WebSocket channel diff updates.
- Применяет diff к локальной копии.
| Сценарий | Действие |
|---|---|
| Новое подключение | GET /api/v1/orderbook/snapshot?symbol=BTCUSDT&depth=50 |
| Пропуск diff (sequence gap) | Запросить новый снэпшот |
| Нормальный поток | Применять diff с sequence+1 |
type OrderBookDiff = { sequence: number; bids: [string, string][]; asks: [string, string][]; }; class OrderBookClient { private bids = new Map<string, string>(); private asks = new Map<string, string>(); private lastSeq = 0; applyDiff(diff: OrderBookDiff) { if (diff.sequence <= this.lastSeq) return; if (diff.sequence !== this.lastSeq + 1) { this.requestSnapshot(); return; } diff.bids.forEach(([p, s]) => s === '0' ? this.bids.delete(p) : this.bids.set(p, s)); diff.asks.forEach(([p, s]) => s === '0' ? this.asks.delete(p) : this.asks.set(p, s)); this.lastSeq = diff.sequence; } } Визуализация: группировка по тикам и depth chart
Реальный order book может иметь тысячи уровней. Для отображения — группировка по «тику» (минимальный шаг цены). Пользователь переключает тик (0.01, 0.1, 1 для BTC/USDT), и мы агрегируем объёмы. Depth chart показывает относительную глубину каждого уровня — зелёный для bids, красный для asks.
Типичные проблемы и их решение
- **Race conditions при отмене и исполнении**: используем RWMutex, но для высокой конкурентности — lock-free структуры. - **Пропуск diff обновлений**: клиент хранит sequence, при разрыве запрашивает полный снэпшот. - **Слишком много уровней в ответе**: ограничиваем depth (top 50) и даём группировку.Что входит в разработку order book
- Архитектура и проектирование: выбор алгоритма matching, схемы репликации.
- Реализация in-memory engine на Go с latency < 100 μs.
- REST API и WebSocket feed со снэпшотами и diff updates.
- Frontend-компоненты на React с grouping и depth chart.
- Интеграция с PostgreSQL для персистентности ордеров.
- Нагрузочное тестирование (100k+ ордеров/сек).
- Документация: OpenAPI, описание протокола, инструкция по развёртыванию.
- Обучение команды заказчика.
- Гарантия и поддержка: 3 месяца после деплоя.
Как мы разрабатываем order book под ключ
- Анализ требований и архитектура.
- Реализация in-memory matching engine.
- REST API + WebSocket feed.
- Frontend-визуализация.
- Интеграция с внешними системами.
- Нагрузочное тестирование и оптимизация.
- Документация и передача.
Производительность
Для биржи с 10–20 парами и умеренным объёмом: один Go-процесс обрабатывает > 50 000 ордеров/сек. При необходимости — шардинг по парам и горизонтальное масштабирование API. Снижение затрат на инфраструктуру за счёт in-memory подхода составляет до 30-40% при высокой нагрузке.
| Метрика | Значение | Условия |
|---|---|---|
| Matching latency | < 100 μs | In-memory, single core |
| Add order throughput | 100k+ ops/sec | Go, Red-Black tree |
| Cancel order | O(1) | Hash map lookup |
| Snapshot generation | < 1 ms | Top 50 levels |
| WS diff broadcast | < 1 ms | After each trade |
Свяжитесь с нами для оценки вашего проекта. Закажите разработку order book под ключ — получите консультацию инженера с опытом 10+ лет в blockchain. Экономия средств на инфраструктуре и повышение производительности торговой площадки — реальные результаты наших проектов.







