Skip to main content

高频交易系统中的大吞吐量订单发送机制

·1 min

1. 需求背景 #

在高频交易系统中,我们面临一个典型场景:需要同时处理三个关联订单(三角套利)。这些订单必须几乎同时发出以确保套利的有效性。

关键挑战:

  • 订单必须同时或几乎同时发出
  • 系统需要处理高并发的订单组
  • 需要保证订单处理的稳定性和可靠性

2. 当前使用的两种处理订单的机制 #

  • 无锁队列机制
    • 订单生成后进入一个无锁队列
    • 多个线程从队列中取订单进行处理
    • 订单的发送通过RestClient进行,RestClient负责管理HTTP连接池并发送请求
  • 分片机制
    • 订单生成后根据某种规则分配到不同的分片
    • 每个分片由固定的线程处理
    • 同一组的订单被分配到同一个分片,确保组内订单的处理一致性
    • RestClient同样负责订单的发送
class OrderShard {
private:
    struct OrderGroup {
        uint64_t groupId;
        uint64_t timestamp;
        std::vector<Order> orders;
    };
    
    std::queue<OrderGroup> orderQueue_;
    std::mutex mutex_;
    std::condition_variable cv_;
    RestClient restClient_;

public:
    void addOrderGroup(OrderGroup group) {
        {
            std::lock_guard<std::mutex> lock(mutex_);
            orderQueue_.push(std::move(group));
        }
        cv_.notify_one();
    }
    
    void processOrders() {
        while (running_) {
            OrderGroup group;
            {
                std::unique_lock<std::mutex> lock(mutex_);
                cv_.wait(lock, [this] { 
                    return !orderQueue_.empty() || !running_; 
                });
                
                if (!running_) break;
                
                group = std::move(orderQueue_.front());
                orderQueue_.pop();
            }
            
            // 批量发送同组订单
            sendOrderGroup(group);
        }
    }

private:
    void sendOrderGroup(const OrderGroup& group) {
        // 使用同一个连接发送组内所有订单
        auto conn = restClient_.getConnection();
        for (const auto& order : group.orders) {
            conn->sendOrder(order);
        }
    }
};

3. 两种机制的执行结果分析 #

  • 无锁队列机制
    • 日志显示组内订单的发送时间差较大,通常在180-220ms之间
    • 存在较大的延迟波动,部分组的最大时间差超过1000ms
总订单组数: 164
存在时间差的组数: 161
最大时间差: 2961.000ms
平均时间差: 308.851ms
  • 分片机制

    • 日志显示组内订单的发送时间差非常小,基本在0-1ms之间
    • 订单几乎同时发出,延迟波动很小
    总订单组数: 416
    存在时间差的组数: 166
    最大时间差: 425.000ms
    平均时间差: 56.991ms
    

4. 机制差异分析 #

  • 无锁队列机制
    • 所有订单进入同一个队列
    • 多个线程从同一队列取任务,即使是无锁的,仍然存在竞争
    • 同一组的三个订单可能被不同线程处理,导致时间差
    • 线程调度的不确定性导致组内订单的发送时间不一致
  • 分片机制
    • 通过分片将同组订单分配到同一线程,避免了线程间的竞争
    • 固定线程处理同一分片,确保了组内订单的处理顺序和时间一致性

5. 适合需求的最佳方案 #

  • 分片机制
    • 理由:分片机制能够确保同组订单的处理一致性,满足几乎同时发出的需求
    • 通过减少线程竞争和调度不确定性,分片机制提供了更稳定的性能

6. 最佳方案的优化方向 #

  • 优化分片策略
    • 根据订单特性优化分片规则,进一步提高处理效率
  • 调整线程池配置
    • 根据系统负载动态调整线程池大小,确保资源的合理利用
  • 优化RestClient连接池
    • 根据请求并发量调整连接池大小,确保请求的快速发送
  • 监控和调优
    • 持续监控系统性能,识别瓶颈并进行调优
    • 使用性能分析工具识别和优化关键路径