Webman不能直接用于交易流水监控,因其缺乏数据一致性、时序聚合和高并发写入能力;必须通过Redis中转+时序数据库(如VictoriaMetrics/TimescaleDB)+异步告警实现完整链路。

Webman 本身不提供交易流水监控能力,必须自己搭链路:接收 → 解析 → 存储 → 查询 → 告警。直接用它当“Zabbix 替代品”会卡在数据一致性、时序聚合、高并发写入三座大山。
为什么不能直接用 Webman 记录交易流水
常见错误是把 $redis->lPush('trade_log', json_encode($data)) 往中间件里一塞就上线——结果发现 Redis 内存爆满、查不到指定时间范围的流水、无法按币种/用户/状态做聚合统计。根本原因在于:Webman 是管道,不是数据库,更不是时序引擎。
- 多 Worker 进程下,
file_put_contents()或内存数组写日志必然丢失或错乱 - Redis List 不支持按时间范围索引,
L RANGE扫全量太慢,L TRIM又容易丢数据 - 没做字段标准化(如金额单位不统一为 satoshi、时间戳混用秒/毫秒),后续 PromQL 或 SQL 查询全报错
必须接入时序数据库才能查“过去1小时 BTC 充值总额”
想算这类指标,靠 MySQL 或普通 Redis 行不通。MySQL 写入吞吐扛不住每秒数千笔流水;Redis 没内置时间窗口聚合函数。唯一可行路径是接入原生时序库:
-
VictoriaMetrics:轻量、单节点可扛每秒 10 万写入,sum_over_time(trade_amount{coin="BTC"}[1h])直接出结果 -
TimescaleDB:基于 PostgreSQL,支持标准 SQL + hypertable 自动分区,适合需要 JOIN 用户表的场景 - 别碰 InfluxDB OSS 版:v2.7 后免费版阉割了连续查询(CQ),无法自动计算 hourly_total 字段
接入关键点:trade_timestamp 必须是毫秒级 Unix 时间戳(13 位),且写入前校验非空、非负;标签(tag)字段如 coin、side、status 要预定义枚举值,避免写入非法字符串导致 series 爆炸。
Webman 2.2.0版本强化了 TCP/UDP 服务支持,优化路由组管理,并增强异步任务处理能力。结合协程与连接池技术,Webman 能轻松应对高并发场景,适用于网站、接口服务、即时通讯、物联网及游戏开发,兼具高性能、灵活扩展与稳定可靠,是多场景 PHP 服务开发的理想选择。
Webman 如何安全接收并转发流水到时序库
核心是避免在 HTTP 请求中直接调用 vm_insert() 或 timescaledb_exec()——网络超时或 DB 拒绝会导致请求阻塞、连接池耗尽。正确做法是:
- 收到流水后,只做最小验证(签名、字段存在性、金额正数),然后
Redis::publish('trade:stream', $json) - 另起一个
Worker进程监听trade:stream,用连接池批量写入 VictoriaMetrics(每 100 条或 100ms flush 一次) - 监听进程必须启用
pcntl和posix,否则onWorkerStart里无法稳定 fork - 千万别用
sleep(0.1)轮询 Redis,改用Redis::subscribe()阻塞等待,CPU 占用从 90% 降到 3%
验证方式:curl -X POST http://localhost:8787/api/trade -d '{"coin":"USDT","amount":"100.00","side":"buy"}' 发一条,再查 VictoriaMetrics 的 /api/v1/series 看是否生成新 series。
告警规则必须脱离 Webman 主循环执行
在 MetricsController 里写 if ($amount > 10000) { sendDingTalk(...) } 是灾难:HTTP 请求线程被钉钉 API 卡住,整条流水链路堵死。真实做法是:
- 所有告警逻辑下沉到独立定时任务(
app/command/AlertCommand.php) - 每 5 秒执行一次:
sum_over_time(trade_amount{coin="BTC"}[5m]) > bool 1000000,命中则写入alert:pendingList - 另起协程消费
alert:pending,用连接池发钉钉/飞书,失败自动重试 3 次后进死信队列 - 告警去重靠
trade_id+rule_hash组合做 Redis SETNX,防止同一笔大额交易触发 20 次通知
最容易被忽略的是时间窗口对齐:Prometheus 的 [5m] 默认按整点切分(如 14:00–14:05),但 Webman 接收时间是毫秒级,必须用 time() - time() % 300 手动对齐,否则告警永远晚 4 分 59 秒。


















