背景
场景:
- 交易撮合系统
挑战:
- 有时间优先约束, 单只股票只能串行操作, 容易导致交易拥堵的瓶颈.
- 一笔交易涉及多份, 例如200股, 存在部分交易, 部分撤单的需求.
- 买卖双方的数量可能不匹配, 一笔撮合交易可能涉及多方.
- 隐蔽问题: 价格挂太高或太低, 无法撮合时, 会导致资源浪费. 类似vacuum, 有长事务, 导致垃圾不能回收, 但是依旧要触发扫描.
- 业务层实现撮合的挑战: 与数据库需要进行很多轮交互, 并且需要在事务中完成, 事务RT和死锁问题增加. 性能弱.
PG解决方案:
- 业务逻辑放在函数内完成, 大幅降低应用与数据库交互, 降低RT.
- advisory lock, skip locked等技术手段避免死锁.
DEMO:
约束:
- 时间优先
- 价格优先
- 买低不买高
- 卖高不卖低
- 限价交易, 指定价格
- 限时交易
- 过期未完成交易则撤单
结构设计:
1、时价表
stockid
price -- 时价
ts
2、买方pipeline
pk
uid
stockid
price
cnt
request_ts
deadline_ts
modify_ts
3、卖方pipeline
pk
uid
stockid
price
cnt
request_ts
deadline_ts
modify_ts
4、交易明细
pk
stockid
buyer
provider
cnt
price
status
request_ts
5、过期订单历史
ops -- 买or卖
pk
uid
stockid
price
cnt
request_ts
deadline_ts
modify_ts
请求需求:
- 新建交易订单
- 修改订单内容
- 撤单
撮合函数逻辑:
参数: 输入stockid, batch次数(loop次数)
逻辑:
loop batch次数
删除过期订单写入过期订单历史表
按规则取出一条最早的待成交记录, 买方和卖方, 时间优先, 并且取待交易数额(cnt)小的.
撮合
更新买、卖表cnt
写交易明细
更新时价表
end loop;
参考
《如何用一个回形针换一栋别墅- openBarter (古人的物物交换市场) 类撮合交易系统》