主页 > 怎么安装imtoken > 数字货币兑换--数字货币兑换系统开发源码分享
数字货币兑换--数字货币兑换系统开发源码分享
##前言
无论是股票交易系统还是数字货币交易系统,都离不开撮合交易引擎,撮合交易引擎是交易平台的核心。同时,优秀的架构设计也将使交易平台的运维和持续开发变得更加容易。本文在深入研究开源项目的基础上,总结了数字货币交易系统的架构设计。
##关于撮合交易系统
匹配技术主要从数据库匹配技术发展到内存匹配技术。这是因为数据库匹配技术越来越不能满足高可靠性金融交易的需求。安全性、可扩展性和易于维护。金融(货币)交易撮合系统包括以下核心模块:
##关于技术选择
交易所平台的技术架构主要考虑安全、分布式、易扩展、容错、低延迟、高并发等特性,以及熔断机制、服务注册与发现、消息服务、服务网关、安全认证、内存数据库、关系数据库等,最终形成以下技术选择:
为分布式基础架构选择 SpringCloud 和 Dubbo。因为SpringCloud知名度更高,所以招到SpringCloud程序员比较好,有利于系统的长期运维升级,而且SpringCloud是基于SpringBoot开发的更亲民,所以选择了SpringCloud。事实上,由于阿里系的强大影响力,Dubbo在国内的使用更加广泛,不同的团队可以根据自己的情况进行选择。引入Hystrix断路器作为容错保护模块,防止单个服务故障,耗尽整个匹配系统容器的线程资源,避免分布式环境中出现大量级联故障。通过第三方客户端访问依赖服务时,实现故障、拒绝、超时或短路的回退逻辑。 Eureka作为服务注册和发现中心来实现中间层服务,从而达到负载均衡和中间层服务故障转移的目的。对于服务网关Spring Cloud Gateway和Zuul的选择,选择Zuul是因为名字比较短。引入 Spring Cloud Security 安全认证模块,构建安全的应用和服务。基于 Spring Boot 和 Spring Security OAuth2,Spring Cloud Security 可以快速创建和实现常见的安全认证方式,如单点登录、令牌中继和令牌交换等。引入 Redis 作为内存数据库,兼作系统数据缓存和内存计算。使用 MySQL 作为关系型数据库,性能测试非常好,对熟悉 MYSQL 的程序员非常友好。消息队列中间件MQ采用Kafka,具有超高性能。
##关于交易所架构的设计
要基于SpringCloud开发基于微服务架构的交易平台,首先需要了解SpringCloud的基础架构。我们熟悉 SpringCloud 微服务架构。如下图所示:
限于篇幅,本文不再详细解读SpringCloud的技术架构。
如何在优秀的微服务框架SpringCloud的基础上搭建事务系统?开源项目 CoinExchange 为交易所设计了如下架构:
撮合交易引擎、API等被拆分为独立的服务,基于SpringCloud的流线型交换结构。
部署图如下:
##关于撮合交易引擎
采用内存匹配的方式,Kafka用于匹配订单信息传输,MongoDB持久化订单交易明细,MySQL记录整体订单交易。市场模块主要负责订单交易的持久化、市场生成、市场推送等服务,包括:
内存匹配事务支持的模式
匹配逻辑流程如下图所示:
p>
示例代码如下:
1 /**
2 * 限价委托单与限价队列匹配
3 * @param lpList 限价对手单队列
4 * @param focusedOrder 交易订单
5 */
6 public void matchLimitPriceWithLPList(TreeMap lpList, ExchangeOrder focusedOrder,boolean canEnterList){
7 List exchangeTrades = new ArrayList<>();
8 List completedOrders = new ArrayList<>();
9 synchronized (lpList) {
10 Iterator> mergeOrderIterator = lpList.entrySet().iterator();
11 boolean exitLoop = false;
12 while (!exitLoop && mergeOrderIterator.hasNext()) {
13 Map.Entry entry = mergeOrderIterator.next();
14 MergeOrder mergeOrder = entry.getValue();
15 Iterator orderIterator = mergeOrder.iterator();
16 //买入单需要匹配的价格不大于委托价,否则退出
17 if (focusedOrder.getDirection() == ExchangeOrderDirection.BUY && mergeOrder.getPrice().compareTo(focusedOrder.getPrice()) > 0) {
18 break;
19 }
20 //卖出单需要匹配的价格不小于委托价,否则退出
21 if (focusedOrder.getDirection() == ExchangeOrderDirection.SELL && mergeOrder.getPrice().compareTo(focusedOrder.getPrice()) < 0) {
22 break;
23 }
24 while (orderIterator.hasNext()) {
25 ExchangeOrder matchOrder = orderIterator.next();
26 //处理匹配
27 ExchangeTrade trade = processMatch(focusedOrder, matchOrder);
28 exchangeTrades.add(trade);
29 //判断匹配单是否完成
30 if (matchOrder.isCompleted()) {
31 //当前匹配的订单完成交易,删除该订单
32 orderIterator.remove();
33 completedOrders.add(matchOrder);
34 }
35 //判断交易单是否完成
36 if (focusedOrder.isCompleted()) {
37 //交易完成
38 completedOrders.add(focusedOrder);
39 //退出循环
40 exitLoop = true;
41 break;
42 }
43 }
44 if(mergeOrder.size() == 0){
45 mergeOrderIterator.remove();
46 }
47 }
48 }
49 //如果还没有交易完,订单压入列表中
50 if (focusedOrder.getTradedAmount().compareTo(focusedOrder.getAmount()) < 0 && canEnterList) {
51 addLimitPriceOrder(focusedOrder);
52 }
53 //每个订单的匹配批量推送
54 handleExchangeTrade(exchangeTrades);
55 if(completedOrders.size() > 0){
56 orderCompleted(completedOrders);
57 TradePlate plate = focusedOrder.getDirection() == ExchangeOrderDirection.BUY ? sellTradePlate : buyTradePlate;
58 sendTradePlateMessage(plate);
59 }
60 }
61
62 /**
63 * 限价委托单与市价队列匹配
64 * @param mpList 市价对手单队列
65 * @param focusedOrder 交易订单
66 */
67 public void matchLimitPriceWithMPList(LinkedList mpList,ExchangeOrder focusedOrder){
68 List exchangeTrades = new ArrayList<>();
69 List completedOrders = new ArrayList<>();
70 synchronized (mpList) {
71 Iterator iterator = mpList.iterator();
72 while (iterator.hasNext()) {
73 ExchangeOrder matchOrder = iterator.next();
74 ExchangeTrade trade = processMatch(focusedOrder, matchOrder);
75 logger.info(">>>>>"+trade);
76 if(trade != null){
77 exchangeTrades.add(trade);
78 }
79 //判断匹配单是否完成,市价单amount为成交量
80 if(matchOrder.isCompleted()){
81 iterator.remove();
82 completedOrders.add(matchOrder);
83 }
84 //判断吃单是否完成,判断成交量是否完成
85 if (focusedOrder.isCompleted()) {
86 //交易完成
87 completedOrders.add(focusedOrder);
88 //退出循环
89 break;
90 }
91 }
92 }
93 //如果还没有交易完,订单压入列表中
94 if (focusedOrder.getTradedAmount().compareTo(focusedOrder.getAmount()) < 0) {
95 addLimitPriceOrder(focusedOrder);
96 }
97 //每个订单的匹配批量推送
98 handleExchangeTrade(exchangeTrades);
99 orderCompleted(completedOrders);
100 }
101
102
103 /**
104 * 市价委托单与限价对手单列表交易
105 * @param lpList 限价对手单列表
106 * @param focusedOrder 待交易订单
107 */
108 public void matchMarketPriceWithLPList(TreeMap lpList, ExchangeOrder focusedOrder){
109 List exchangeTrades = new ArrayList<>();
110 List completedOrders = new ArrayList<>();
111 synchronized (lpList) {
112 Iterator> mergeOrderIterator = lpList.entrySet().iterator();
113 boolean exitLoop = false;
114 while (!exitLoop && mergeOrderIterator.hasNext()) {
115 Map.Entry entry = mergeOrderIterator.next();
116 MergeOrder mergeOrder = entry.getValue();
117 Iterator orderIterator = mergeOrder.iterator();
118 while (orderIterator.hasNext()) {
119 ExchangeOrder matchOrder = orderIterator.next();
120 //处理匹配
121 ExchangeTrade trade = processMatch(focusedOrder, matchOrder);
122 if (trade != null) {
123 exchangeTrades.add(trade);
124 }
125 //判断匹配单是否完成
126 if (matchOrder.isCompleted()) {
127 //当前匹配的订单完成交易,删除该订单
128 orderIterator.remove();
129 completedOrders.add(matchOrder);
130 }
131 //判断焦点订单是否完成
132 if (focusedOrder.isCompleted()) {
133 completedOrders.add(focusedOrder);
134 //退出循环
135 exitLoop = true;
136 break;
137 }
138 }
139 if(mergeOrder.size() == 0){
140 mergeOrderIterator.remove();
141 }
142 }
143 }
144 //如果还没有交易完,订单压入列表中,市价买单按成交量算
145 if (focusedOrder.getDirection() == ExchangeOrderDirection.SELL&&focusedOrder.getTradedAmount().compareTo(focusedOrder.getAmount()) < 0
146 || focusedOrder.getDirection() == ExchangeOrderDirection.BUY&& focusedOrder.getTurnover().compareTo(focusedOrder.getAmount()) < 0) {
147 addMarketPriceOrder(focusedOrder);
148 }
149 //每个订单的匹配批量推送
150 handleExchangeTrade(exchangeTrades);
151 if(completedOrders.size() > 0){
152 orderCompleted(completedOrders);
153 TradePlate plate = focusedOrder.getDirection() == ExchangeOrderDirection.BUY ? sellTradePlate : buyTradePlate;
154 sendTradePlateMessage(plate);
155 }
156 }
关于区块链钱包连接
每种货币对应不同的数据访问方式。大多数区块链项目的钱包操作方式都是相同或非常相似的,比如比特币衍生品如BTC、LTC、BCH、BSV、BCD,以及它们的API。操作方法几乎相同;再比如ETH,当你掌握了一个合约币的操作后数字货币交易平台官网,其他基于ETH发行的数字货币的操作方法几乎是一样的。所以基本上当你花时间去理解一个时,你就会理解一堆硬币。
本项目使用的钱包操作方案也不同,我们尽量给大家展示不同的用法:
一般来说,当交易所之间的资金量不大的时候,你可以自己去探索数字货币交易平台官网,但是当交易所的资金量很大的时候,如果你对自己操作钱包不是很有信心,你也可以使用第三方钱包服务。当然,这需要你和钱包服务商协商,交年费什么的。
下图是交易平台充值逻辑的简单时序图:
总结
通过以上我们对交易所的整体架构基本有了一定的了解。
感谢阅读,如果觉得这篇文章不错,记得点赞关注