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

转自廖雪峰老师的《交易系统如何确保账簿100%准确》

这篇文章阐述了一个交易系统中对账功能的关键,即:时刻保证资产负债表总额始终为 0。

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

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

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

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

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

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
DEBTUSD-10000
ABTC1.2
BUSD4000
CBTC2.8
DUSD6000

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

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

usercurrencybalance
DEBTBTC-4
DEBTUSD-10000
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 ,计算极其简单。

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

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/558840.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

通俗易懂的SpringBoot教程---day1---Springboot入门教程介绍

通俗易懂的SpringBoot教程—day1—教程介绍 教程介绍: 初级教程: 一、 Spring Boot入门 二、 Spring Boot配置 三、 Spring Boot与日志 四、 Spring Boot与Web开发 五、 Spring Boot与Docker:Docker容器 六、 Spring Boot与数据访问&#x…

Java 8中获取参数名称

本文转自廖雪峰老师的:《在Java 8中获取参数名称》 在Java 8之前的版本,代码编译为class文件后,方法参数的类型是固定的,但参数名称却丢失了,这和动态语言严重依赖参数名称形成了鲜明对比。现在,Java 8开始…

通俗易懂的SpringBoot教程---day2---Springboot配置文件

通俗易懂的SpringBoot教程—day2—Springboot配置文件 1、配置文件 SpringBoot使用一个全局的配置文件,配置文件名是固定的; •application.properties •application.yml 配置文件的作用:修改SpringBoot自动配置的默认值;Spring…

Could not resolve host: 'localhost 报错解决办法

Could not resolve host: localhost 报错解决办法 面向Windows的: 零基础的我一直卡在这一步骤下: 首先要先在Windows安装curl:安装方式参考:https://blog.csdn.net/weixin_41986096/article/details/86646365 按照完之后&…

当面试官问我————为什么String是final的?

面试官:你好,能看得清下面这张图吗? 我:可以的。 面试官:恩,好的。呃,你能不能说一说为什么String要用final修饰? 我:final意味着不能被继承或者被重写,Str…

当面试官问我————Java是值传递还是引用传递?

面试官:你好,你能说出下面个程序的执行结果吗? public class Test {public static void main(String[] args) {String name "Scott";int age 5;User user new User();user.setName(name);user.setAge(age);System.out.println(…

ubuntu系统下Jenkins和tomcat的安装与配置

ubuntu 安装 JDK ubuntu的安装我们采取最简单的方式安装 直接用apt-get的方式 sudo apt-get install openjdk-8-jdk 安装器会提示你同意 oracle 的服务条款,选择 ok 然后选择yes 即可 ubuntu 安装tomcat8 通过apt安装 tomcat8 sudo apt-get install tomcat8 tomcat8-docs t…

String字符串拼接小例

>>>写出下面程序运行结果: public class StringTest {public static void main(String[] args) {String s1 "Programming";String a "Program";String b "ming";String s2 "Program" "ming";Stri…

看完这篇文章,还不懂nginx,算我输

看完这篇文章,还不懂nginx,算我输 参考:https://mp.weixin.qq.com/s/PeNWaCDf_6gp2fCQa0Gvng 1. Nginx产生~ Nginx 同 Apache 一样都是一种 Web 服务器。基于 REST 架构风格,以统一资源描述符(Uniform Resources Id…

一篇博客读懂设计模式之---工厂模式

设计模式之—工厂模式 工厂模式: 创建过程: 创建Shape接口 public interface Shape {void draw(); }创建实现类: public class Circle implements Shape {Overridepublic void draw() {System.out.println("this is a circle!"…

一篇博客读懂设计模式之-----策略模式

设计模式之策略模式 在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的对象 定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。 主要解决:在有多种算法相似的情况下,使用 if…else 所带来的复杂和…

Java并发编程实战————恢复中断

中断是一种协作机制,一个线程不能强制其他线程停止正在执行的操作而去执行其他操作。 什么是中断状态? 线程类有一个描述自身是否被中断了的boolean类型的状态,可以通过调用 .isInterrupted() 方法来查看。官方解释如下: 简单来…

一篇博客读懂设计模式之---模板方法模式

设计模式之模板方法模式: 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 简而言之就是:父类定义了骨架(调用哪些方法及其顺序)…

一篇读懂--mybatis的缓存

一篇读懂–mybatis的缓存 MyBatis的缓存指的是缓存查询结果,当以后使用相同的sql语句、传入相同的参数进行查询时,可直接从mybatis本地缓存中获取查询结果,而不必查询数据库。 mybatis的缓存包括一级缓存、二级缓存,一级缓存默认…

Spring Boot————BeanCreationNotAllowedException异常分析

引言 在对数据库进行新增记录的JUnit测试时,抛出一个BeanCreationNotAllowedException异常: 异常分析与解决 异常信息太长,图片截不下,粘贴来看: Exception in thread "pool-2-thread-1" org.springframew…

一篇博客读懂设计模式之---委派模式

一篇博客读懂设计模式之—委派模式 委派模式可能大家听起来不太熟悉,但是在代码开发的时候却很好用,下面从几个方面来介绍一下 what:是什么? 委派模式:顾名思义,委托其他对象或者实例来帮我们完成任务&am…

Jackson快速入门

引言 上一篇博客《XML模板解析————Dom4j解析xml案例分析》简单讲解了关于xml模板的解析,使用到了dom4j,这篇文章其实算是个姊妹篇,都是对于目前工作中的一些任务,如xml、json相互解析所涉及到的知识。 但是相对于xml而言&am…

一篇文章读懂MySQL的各种联合查询

一篇文章读懂MySQL的各种联合查询 联合查询是指将两个或两个以上的表的数据根据一定的条件合并在一起! 联合查询主要有以下几种方式: 全连接:将一张表的数据与另外一张表的数据彼此交叉联合查询出来 举例如下: 先建两张表: CR…

一篇文章看懂@Scheduled定时器/@Async/CompletableFuture

一篇文章看懂Scheduled定时器/Async/CompletableFuture Scheduled注解解析: 1.cron:最重要的一个参数 cron表达式[秒] [分] [小时] [日] [月] [周] [年]([年]可省略) 简单了解一下,网上有现成的工具 示例&#xff…

一篇搞懂HTTP协议

本文转自 :flyhero 码上实战《一个HTTP打趴80%面试者》 HTTP协议简介 HTTP(超文本传输协议)是应用层上的一种客户端/服务端模型的通信协议,它由请求和响应构成,且是无状态的。(暂不介绍HTTP2) 协议&…