[英]Order Matching System Design : how to design an efficient and secure crypto account system
Context语境
I am working in a crypto exchange company as backend engineer.我在一家加密货币交易所公司担任后端工程师。 Recently, we are facing a performance issue in our matching system.
最近,我们的匹配系统面临性能问题。 When user's order got match, system will deduct or add order's amount to their account.
当用户的订单匹配时,系统将扣除或添加订单金额到他们的账户。 This process will lock user's account with database write lock.
此过程将使用数据库写锁锁定用户的帐户。
Problem问题
If users make order too frequently in a short time, lots of order will try to lock the same record.如果用户在短时间内下单过于频繁,大量的订单会尝试锁定同一条记录。 Under such lock contention situation, DB transaction will timeout and retry until finishing matching process.
在这种锁竞争的情况下,数据库事务将超时并重试,直到完成匹配过程。 Meanwhile db CPU usage increase quickly.
同时 db CPU 使用率迅速增加。 We are trying to fix this lock contention problem.
我们正在尝试解决此锁定争用问题。
Present System Design目前的系统设计
CREATE TABLE `user_accounts` (
`user_id` bigint(20) unsigned NOT NULL,
`btc` decimal(65,0) NOT NULL DEFAULT '0' COMMENT 'btc balance',
`btc_trade` decimal(65,0) NOT NULL DEFAULT '0' COMMENT 'trading btc amount',
`eth` decimal(65,0) NOT NULL DEFAULT '0',
`eth_trade` decimal(65,0) NOT NULL DEFAULT '0',
`usdt` decimal(65,0) NOT NULL DEFAULT '0',
`usdt_trade` decimal(65,0) NOT NULL DEFAULT '0',
`sol` decimal(65,0) NOT NULL DEFAULT '0',
`sol_trade` decimal(65,0) NOT NULL DEFAULT '0',
`balance_checksum` VARCHAR(255) NOT NULL DEFAULT '',
....
)
Above db schema is used to store user's balance and matching flow is that:上面的 db schema 用于存储用户的余额,匹配流程是:
SELECT btc, btc_trade, usdt, usdt_trade, balance_checksum FROM user_accounts WHERE user_id =? FOR UPDATE
UPDATE user_accounts SET btc_trade=?, usdt=?, balance_checksum=? WHERE user_id =?
Possible Solutions可能的解决方案
After some brainstorming, we came out some of ideas.经过一番头脑风暴,我们得出了一些想法。
account_balances
db schema:account_balances
数据库架构: Current schema store all currencies in the same record, however the system only use two currencies during matching process.当前模式将所有货币存储在同一记录中,但是系统在匹配过程中仅使用两种货币。 Some of developer present new db schema like:
一些开发人员提出了新的数据库架构,例如:
CREATE TABLE `new_user_accounts` (
`id` bigint(20) unsigned NOT NULL,
`user_id` bigint(20) unsigned NOT NULL,
`currency` VARCHAR(50) NOT NULL DEFAULT '',
`amount` decimal(65,0) NOT NULL DEFAULT '0',
`lock_amount` decimal(65,0) NOT NULL DEFAULT '0',
`balance_checksum` VARCHAR(255) NOT NULL DEFAULT '',
....
)
This solution might reduce some lock contention situation, however most of order require trading USDT or other fiat currencies.这种解决方案可能会减少一些锁定竞争的情况,但是大多数订单需要交易 USDT 或其他法定货币。 Therefore, I proposed the second solution.
因此,我提出了第二种解决方案。
If we remove checksum value from db schema, we can update balance by using SQL UPDATE user_accounts SET btc_trade=btc_trade-?, usdt=usdt+? WHERE user_id =? AND btc_trade >=?
如果我们从 db 模式中删除校验和值,我们可以使用 SQL
UPDATE user_accounts SET btc_trade=btc_trade-?, usdt=usdt+? WHERE user_id =? AND btc_trade >=?
UPDATE user_accounts SET btc_trade=btc_trade-?, usdt=usdt+? WHERE user_id =? AND btc_trade >=?
. . With this update SQL, the transaction does not require the lock.
通过此更新 SQL,事务不需要锁定。 We can solve lock contention problem completely.
我们可以彻底解决锁竞争问题。
One of problem of this solution is that I have to find out a alternative for checksum value.该解决方案的一个问题是我必须找到校验和值的替代方案。 Is there better way to prevent from modifying balance directly by db operation or better way to monitor illegal balance modification operation.
有没有更好的方法来防止直接通过db操作修改余额或更好的方法来监控非法余额修改操作。
Have you considered introducing a pipeline for redis?您是否考虑过为 redis 引入管道?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.