auto_trade_sys/docs/MULTI_USER_ARCHITECTURE.md
薇薇安 86b85c2609 a
2026-01-25 11:19:39 +08:00

7.8 KiB
Raw Blame History

多用户(多账号)架构评估与落地方案(草案)

本文档基于你提出的多用户需求给出数据隔离边界、并发模型、Redis/DB 设计、以及 2核4G 服务器负载评估与分阶段落地路线。


目标与约束

目标(对应你的 6 点)

  1. 每个用户使用自己的 API KEY
  2. 每个用户独立自动交易、独立持仓
  3. 每个用户独立配置
  4. 交易推荐全局共用
  5. 订单/交易记录独立
  6. 错误日志全局共用

关键约束

  • 币安限频是关键瓶颈:公共行情接口通常按 IP 限频,单纯“多 key”无法线性扩容必须通过共享行情缓存降低请求。
  • 隔离优先级:下单/持仓/配置/订单记录必须强隔离;推荐/行情/错误日志可以共享。

数据归属与隔离Data Ownership

A. 全局共享(所有用户共用)

  • 推荐Recommendations:一份全局 Redis Snapshot/List
    • 建议 Keyats:recommendations:snapshot
    • 后端/前端只读(不在请求中触发扫描/生成)
  • 行情热数据Market Data全局缓存Redis
    • ats:md:mark_price:all(短 TTL比如 2~5s
    • ats:md:ticker_24h:allTTL 10~30s
    • ats:md:klines:{symbol}:{interval}:{limit}TTL 30~120s
  • 错误日志Logs:全局流
    • 继续使用 ats:logs:{error|warning|info}
    • 每条日志建议增加字段:account_id(便于筛选定位)

B. 用户私有(必须隔离)

  • API KEY/SECRET敏感:按账号独立存储(必须加密)
  • 交易配置:按账号独立
    • DB(account_id, config_key) 唯一
    • Redisats:cfg:{account_id}hash
  • 自动交易运行态/热数据(可选但推荐)
    • ats:positions:{account_id}(更快的 UI 展示/减少后端压力)
    • ats:orders:pending:{account_id}(挂单/入场状态)
    • ats:stats:{account_id}:*(每日下单数、成交数、撤单数等)
  • 交易/订单记录:按账号独立
    • DB 表:trades 增加 account_id;统计/查询均按账号过滤

并发模型:是否需要多线程/多进程?

结论:不推荐多线程。更推荐以下两种模型之一:

方案 1推荐先落地每个账号一个 trading_system 进程Supervisor 管理)

  • 优点
    • 隔离强:某个账号异常/限频/崩溃不影响其他账号
    • 上线快:对现有单账号 trading_system 改动最少
    • 运维简单Supervisor 一账号一进程
  • 缺点
    • 进程数随账号增长(内存占用会上升)
    • 若每进程都重复拉行情,会触发 IP 限频(必须配合“全局行情缓存”)

方案 2后期优化单进程 + asyncio 多账号 worker

  • 优点
    • 资源更省,便于共享行情缓存/HTTP Session
  • 缺点
    • 隔离弱:某个账号阻塞/异常可能影响整体
    • 实现复杂:需要更严格的超时/限频/异常隔离与任务监控

Redis 用法:减轻后端与交易系统压力的关键

建议将 Redis 分为四层:

  1. 全局行情缓存层(降低公共接口请求)
  2. 全局推荐层(只读 snapshot避免“刷新=触发扫描”)
  3. 账号配置层ats:cfg:{account_id}
  4. 账号运行态层positions/pending/stats

额外建议:

  • 使用短 TTL + 分布式锁(你已有 lock 设计),避免并发刷新造成浪涌。

数据库改造(最小必要变更)

  1. 新增 accounts 表:
    • id, name, api_key_enc, api_secret_enc, status, created_at ...
    • API Key 必须加密存储(服务端用 master key 解密)
  2. trading_config 增加 account_id(或新表 trading_config_accounts
  3. trades 增加 account_id
  4. account_snapshots 增加 account_id
  5. 其余按需positions、signalssignals 可全局positions 必须私有)

2核4G 负载评估(粗略)

负载主要来自两块:

  1. 公共行情拉取/指标计算(全局)
  2. 每账号的下单/持仓同步/风控计算(私有)

不做共享行情(不推荐)

  • 每账号都拉 klines/mark price/ticker会先撞到 币安 IP 限频2c4g 也撑不住。

做共享行情 + 推荐全局(推荐)

  • 公共行情只拉 1 份Redis 分发),账号 worker 只消费缓存 + 下单/持仓同步。
  • 2c4g 在“波段低频”(如 15min 扫描、每账号持仓 0~5场景下通常可支撑 10~30 个账号(视持仓监控方式与限频策略而定)。
  • 若每个账号都对每个持仓开 WebSocket 监控,上限会明显降低(更建议用全局 mark price + 定时校验替代/降频)。

分阶段落地路线(推荐)

Phase 1最快上线强隔离、成本最低

  • accounts + account_id 改造DB/API/前端)
  • 每账号一个 trading_system 进程Supervisor
  • 推荐/行情继续全局缓存Redis
  • 日志全局流(带 account_id

Phase 2提升承载与稳定性

  • 抽全局 MarketDataService行情/klines 统一刷新一次)
  • 每账号 worker 只做决策/下单,减少公共 API 调用
  • 降低 per-position websocket 数量(用 mark price 缓存替代)

面向“更多用户”的演进战略准备(从现在就要做对的几件事)

你问“每账号一进程是不是终极方案”。我的建议是把它当作长期默认架构,并提前把“可演进”埋点做对,这样未来扩容不会推倒重来。

1固定边界所有“私有数据”必须天然带 account_id

  • 数据库trades / trading_config / account_snapshots / positions(若有) 都必须有 account_id,且所有查询默认按 account_id 过滤。
  • Redis:账号私有数据统一命名空间:
    • ats:cfg:{account_id}trading_config:{account_id}(一账号一份配置 hash
    • ats:positions:{account_id}ats:orders:pending:{account_id}
  • API:所有与交易/配置/统计相关的接口都要支持 account_idHeader 或 Path哪怕当前只有一个账号。

这一步一旦做对,未来从“多进程”演进到“多 worker/分布式”几乎不改数据层。

2把“共享层”单独做成服务推荐/行情永远不绑定账号

  • 推荐:一份全局 snapshot你已拆成独立推荐进程/服务),后面可水平扩容但要有锁。
  • 行情:建议尽早演进为全局 MarketDataService单实例拉取 + Redis 分发),账号 worker 只消费缓存。

这一步是从 10~30 账号走向 100+ 账号的关键,否则会先撞 Binance IP 限频。

3演进路线从易到难逐步替换不做“重写”

  1. 阶段A现在每账号一个进程Supervisor
    • 最稳、隔离最好、上线快
  2. 阶段B账号增多:引入“控制器 + worker”但仍可单机
    • 控制器负责:调度、限频预算、健康检查、任务重启
    • worker 负责:每账号决策/下单/同步(可仍按进程隔离)
  3. 阶段C规模更大:队列化/分布式K8s/多机)
    • 账号按 account_id 分片到不同节点sharding
    • 共享服务(行情/推荐)做成单独部署,或按区域分片

4安全策略提前统一API Key/Secret 必须与“普通配置”分离

  • 强烈建议API Key/Secret 存 accounts 表,加密存储(服务端 master key 解密),前端永不回传 secret 明文。
  • 交易进程只拿到自己账号的解密结果(进程隔离的优势)。

风险提示与建议

  • 安全API Key 必须加密存储;前端永远不返回明文 secret。
  • 限频:公共接口一定要共享缓存;多账号并发拉行情会让整体不可用。
  • 隔离:交易执行建议多进程优先;后期再做单进程多 worker 的资源优化。