後端2026

高效能加密貨幣交易所後端

以 Go 打造的分散式撮合系統,拆分 gateway、order-service、matching-engine、market-data-service,並實作 Transactional Outbox、Leader Election、批次寫入與架構級壓測驗證。

高效能加密貨幣交易所後端

專案概述

這是一個以 Go 從零打造的高效能交易所後端,核心目標不是只做出下單 API,而是完整驗證高併發交易系統在一致性、高可用、事件流、結算正確性與即時行情推播上的工程難題。系統目前拆分為 gateway、order-service、matching-engine、market-data-service 四個微服務,透過 PostgreSQL、Redis 與 Kafka/Redpanda 串起下單、撮合、結算、訂單狀態更新與 WebSocket 行情推播。除了功能實作,我也為它補上 Prometheus/Grafana 指標、k6 架構級壓測與 staging/ECS 部署腳本,讓這個專案更接近可驗證、可維運的生產級系統。

技術挑戰與解決方案

雙寫一致性與事件可靠投遞

下單流程同時需要鎖資金、建立訂單與發布 Kafka 事件;若資料庫提交成功但訊息未送出,系統就會出現帳務與撮合狀態不一致的雙寫風險。

解決方案:
在 PlaceOrder 的同一個 PostgreSQL transaction 內同時寫入 order 與 outbox message。背景 Outbox Worker 以批次輪詢加上 SKIP LOCKED 發送至 exchange.orders,提供 at-least-once 語意;下游結算再配合 Trade ID 與狀態檢查做冪等防禦,消除傳統 DB + MQ 雙寫缺口。

撮合引擎高可用與防腦裂

matching-engine 需要支援多副本待命,但同一交易對若被兩個實例同時消費,會造成重複成交與帳務災難。

解決方案:
使用 PostgreSQL 的 partition_leader_locks 表實作 leader election,透過 upsert + where 的原子更新與單調遞增 fencing token,確保只有當前 Leader 能處理分區事件。舊 Leader 即使短暫復活,後續寫入也會因過期 token 被拒絕,避免 split-brain。

非同步結算中的死結與冪等性

撮合後的 TX2 需要同時更新 maker / taker 訂單、帳戶餘額、locked 資金與成交紀錄;Kafka 重複投遞或高併發 row lock 競爭都可能造成重複結算或死結。

解決方案:
將結算獨立為 atomic settlement transaction,對 Order / Account 以固定排序取得鎖,並以 Trade ID 唯一鍵、TX 內二次確認與已完成路徑跳過機制實作多層冪等防線。對市價單剩餘保證金則在結算流程中一併解鎖退款,確保帳務最終一致。

造市商批次下單與高頻寫入吞吐

造市商與套利機器人會在極短時間內送出大量訂單,逐筆 HTTP 與 INSERT 會被連線往返與 row lock 成本拖垮。

解決方案:
額外提供 /orders/batch 給高頻寫入場景,底層使用 pgx.CopyFrom 做批次寫入,並在 Go 應用層先依 UserID / Currency 做雙重記憶體排序,降低資料庫 row lock 交錯順序造成的死結風險,讓批次模式在壓測中能明顯拉高吞吐量。

即時行情扇出與可觀測性驗證

交易事件不只要寫得快,還要能穩定推到大量 WebSocket 用戶端;若缺少跨服務指標,也很難判斷瓶頸是在 HTTP、Kafka、撮合還是推播層。

解決方案:
將 WebSocket 扇出獨立為 market-data-service,專職消費 exchange.orderbook、exchange.trades、exchange.order_updates 事件,避免慢速連線反壓主交易鏈路。並補齊 Prometheus 指標與 Grafana dashboard,配合 k6 執行 E2E latency、Market Storm、Spike 等場景,從 golden signals 與業務延遲兩個角度驗證系統。

系統架構

gateway 負責統一入口、Redis Sliding Window 限流、Idempotency-Key 防重複送單與反向代理;order-service 處理 HTTP API 與 TX1,完成鎖資金、建單與寫入 outbox,並在背景批次投遞 exchange.orders;matching-engine 透過 PostgreSQL leader election 與 fencing token 維持 Active-Standby,冷啟動時從 DB 還原活動訂單,在記憶體中執行 Price-Time Priority 撮合,再發布 settlements、trades 與 orderbook 事件;market-data-service 專注消費 Kafka 並扇出 WebSocket 即時資料。整體部署以 Docker Compose 做本地整合,以 AWS ECS、Terraform 與 ecspresso 管理 staging 微服務環境。

學習與心得

這次重構讓我從「會做 API」進一步走到「能設計交易系統」。我實際處理了雙寫一致性、非同步結算、split-brain 防護、批次寫入、防死鎖、慢速 WebSocket consumer 影響隔離,以及如何用壓測與監控去證明系統不是看起來能跑,而是真的在高併發下仍可解釋、可觀測、可恢復。這也讓我更確定,高流量系統的價值不只在吞吐量,更在於失敗時是否仍能維持資料正確性與可操作性。

技術棧

後端

Go 1.25GinPrice-Time PriorityLeader Election

資料庫

PostgreSQLRedispgx v5

事件流與可靠性

Kafka / RedpandaTransactional OutboxAtomic SettlementIdempotency

部署

DockerAWS ECSTerraformecspresso

監控與可觀測性

PrometheusGrafanaCloudWatchk6