IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

交易系统如何确保账簿100%准确

廖雪峰的官方网站 2018-12-26 23:38:42 累计浏览 2,350 次
本机暂存

   交易系统中,对账是一个大问题。对账处理不好,不但需要花费大量的人力去处理账簿,还要承担很大的线上修改账簿的风险。

   如果系统能自动化保证账簿每时每刻100%准确,不能说一劳永逸地解决了所有问题,至少解决了绝大部分问题。

   如何对账,能时刻确保账簿100%准确?

   交易系统中,用户余额存储在账户表中。例如,一个比特币交易系统,假设用户有BTC和USD两种资产,要确保账簿余额是对的,一个设计的关键点就是:时刻保证整个系统的资产负债表为零!

   设想账户表的初始状态,用户A、B、C、D分别存入了数量不等的BTC和USD:

usercurrencybalance
ABTC1.2
BUSD4000
CBTC2.8
DUSD6000

   无论这些用户如何交易,以什么价位交易,最终的结果只是BTC和USD在账户之间移动,其总额并不会增减:

usercurrencybalance
ABTC0.2
AUSD3000
BBTC1.0
BUSD1000
CBTC0.8
CUSD6000
DBTC2.0

   把交易手续费考虑进来,其实也是一样的,只是用户的资产有很少一部分被移动到了系统手续费账户中:

usercurrencybalance
ABTC0.2
AUSD2997
BBTC1.0
BUSD1000
CBTC0.8
CUSD5994
DBTC2.0
FEEUSD9

   上面的账户表不好对账,是因为根据“资产负债表总额始终为零”这一基本原理,缺少一个关键的“负债”账户。

   如果把初始状态加入负债账户:

usercurrencybalance
DEBTBTC-4
DEBTUSD10000
ABTC1.2
BUSD4000
CBTC2.8
DUSD6000

   整个账户表的余额加起来就一定为零。

   随着交易的进行,无论资产如何转移,最终的账户余额也一定为零:

usercurrencybalance
DEBTBTC-4
DEBTUSD10000
ABTC0.2
AUSD2997
BBTC1.0
BUSD1000
CBTC0.8
CUSD5994
DBTC2.0
FEEUSD9

   因此,可以设计出对账的基本逻辑:

SELECT SUM(balance) FROM ACCOUNTS GROUP BY currency;

   在每笔交易后执行该SQL语句,如果账簿无误,结果集必定每一行均为0

   考虑到对账程序的执行效率,可以把它放到只读从库执行,不影响交易本身。

   更进一步,考虑系统初始状态的账户表:

usercurrencybalance

   (无记录)

   当用户X存入USD 1500后,要保证资产负载表为0,该存款操作本质上是一个资产转移过程:USD 1500从DEBT账户转移到用户X的账户:

usercurrencybalance
DEBTUSD-1500
XUSD1500

   取款过程则恰好相反,它是用户资产转移到DEBT账户的过程,体现为DEBT账户余额增加(从负更多到负更少)。

   对于财务人员来讲,用户总资产其实就是ABS(DEBT) - FEE,计算极其简单。

   可见,一个清晰简洁而可靠的设计,不但有力地保证了系统的安全性,而且大大降低了财务对账成本。

同分类推荐文章

  1. 等了十年的 Go 链式管道,终于来了:seq 让你像写 Scala 一样写 Go (2026-06-25 18:38:18)
  2. Go 实验特性详解 (2026-06-21 10:05:27)
  3. amd64 微架构级别对 Go 程序性能提升多少? (2026-06-21 09:38:49)

查看更多 后端 文章 →

建议继续学习

  1. 内存表在同步环境注意事项 (累计阅读 5,718)
  2. 多IDC的数据分布设计(一) (累计阅读 4,413)
  3. 深入浅出cassandra 4 数据一致性问题概述 (累计阅读 3,835)
  4. sql_slave_skip_counter参数 (累计阅读 2,385)
  5. 使用 SysRq 键安全重启挂起的 Linux (累计阅读 2,009)
  6. MySQL relay_log_purge=0 时的风险 (累计阅读 1,857)