提问人:vicxu 提问时间:7/25/2022 最后编辑:vicxu 更新时间:8/4/2022 访问量:225
订单匹配系统设计:如何设计高效安全的加密账户系统
Order Matching System Design : how to design an efficient and secure crypto account system
问:
上下文
我在一家加密货币交易所公司担任后端工程师。最近,我们的匹配系统面临性能问题。当用户的订单匹配时,系统将扣除或添加订单金额到他们的账户中。此过程将使用数据库写锁锁定用户帐户。
问题
如果用户在短时间内过于频繁地下单,大量订单会试图锁定同一条记录。在这种锁争用情况下,数据库事务将超时并重试,直到完成匹配过程。同时,db CPU 使用率快速增加。我们正在尝试解决此锁争用问题。
当前系统设计
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 '',
....
)
上面的 db schema 用于存储用户的余额和匹配流程:
- 如果用户的订单在btc/usdt交易对上匹配,系统首先执行此sql。
SELECT btc, btc_trade, usdt, usdt_trade, balance_checksum FROM user_accounts WHERE user_id = ? FOR UPDATE
- 使用金额值和校验和来验证用户余额的正确性。此校验和值可以防止直接通过 db 操作修改余额。
- 如果余额验证通过,系统会根据更新的金额生成新的校验和,并执行更新SQL。
UPDATE user_accounts SET btc_trade=?, usdt=?, balance_checksum=? WHERE user_id = ?
可能的解决方案
经过一番头脑风暴,我们提出了一些想法。
- 重新设计数据库架构:
account_balances
当前架构将所有货币存储在同一条记录中,但系统在匹配过程中仅使用两种货币。一些开发人员提出了新的数据库模式,例如:
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 '',
....
)
这种解决方案可能会减少一些锁争用的情况,但大多数订单需要交易USDT或其他法定货币。因此,我提出了第二种解决方案。
- 摆脱校验和机制
如果我们从数据库模式中删除校验和值,我们可以使用 SQL 更新余额 .使用此更新 SQL,事务不需要锁。我们可以完全解决锁争用问题。UPDATE user_accounts SET btc_trade=btc_trade-?, usdt=usdt+? WHERE user_id = ? AND btc_trade >= ?
此解决方案的问题之一是我必须找到校验和值的替代方案。有没有更好的方法来防止直接通过数据库操作修改余额,或者更好的方法来监控非法余额修改操作。
答:
评论