高并发转账系统设计方案

📅 发布时间:2026/7/13 16:47:20 👁️ 浏览次数:
高并发转账系统设计方案
目录1. 系统架构设计1.1 核心架构模式1.2 技术栈选择2. 数据库设计2.1 核心表结构3. 核心代码实现3.1 转账服务接口3.2 账户服务实现3.3 转账服务实现3.4 分库分表策略4. 性能优化方案4.1 缓存策略4.2 批量处理优化4.3 异步补偿机制5. 监控和告警5.1 监控指标6. 压力测试配置6.1 JMeter测试计划7. 部署配置7.1 Docker Compose配置8. 关键优化点总结1. 系统架构设计1.1 核心架构模式应用层 → 业务层 → 数据层 ↓ 消息队列 ←→ 分布式缓存 ↓ 数据库集群1.2 技术栈选择框架: Spring Boot 3.x + Spring Cloud数据库: MySQL 8.0 + Redis 7.x消息队列: RocketMQ/Kafka注册中心: Nacos分布式事务: Seata监控: Prometheus + Grafana压测: JMeter2. 数据库设计2.1 核心表结构-- 账户表 CREATE TABLE account ( id BIGINT PRIMARY KEY COMMENT '账户ID', account_no VARCHAR(32) UNIQUE NOT NULL COMMENT '账户编号', user_id BIGINT NOT NULL COMMENT '用户ID', balance DECIMAL(20,2) NOT NULL DEFAULT 0.00 COMMENT '余额', frozen_balance DECIMAL(20,2) NOT NULL DEFAULT 0.00 COMMENT '冻结金额', version INT NOT NULL DEFAULT 0 COMMENT '版本号', currency VARCHAR(3) NOT NULL COMMENT '货币类型', status TINYINT NOT NULL DEFAULT 1 COMMENT '状态:1正常,2冻结', create_time DATETIME DEFAULT CURRENT_TIMESTAMP, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_user_id (user_id), INDEX idx_account_no (account_no) ) ENGINE=InnoDB COMMENT='账户表'; -- 账户流水表 CREATE TABLE account_flow ( id BIGINT PRIMARY KEY, flow_no VARCHAR(64) UNIQUE NOT NULL COMMENT '流水号', account_id BIGINT NOT NULL COMMENT '账户ID', amount DECIMAL(20,2) NOT NULL COMMENT '变动金额', balance DECIMAL(20,2) NOT NULL COMMENT '变动后余额', flow_type TINYINT NOT NULL COMMENT '流水类型:1收入,2支出', biz_type VARCHAR(32) NOT NULL COMMENT '业务类型', biz_no VARCHAR(64) NOT NULL COMMENT '业务单号', remark VARCHAR(255) COMMENT '备注', create_time DATETIME DEFAULT CURRENT_TIMESTAMP, INDEX idx_account_id_time (account_id, create_time), INDEX idx_biz_no (biz_no) ) ENGINE=InnoDB COMMENT='账户流水表'; -- 转账记录表 CREATE TABLE transfer_record ( id BIGINT PRIMARY KEY, transfer_no VARCHAR(64) UNIQUE NOT NULL COMMENT '转账单号', from_account_no VARCHAR(32) NOT NULL COMMENT '转出账户', to_account_no VARCHAR(32) NOT NULL COMMENT '转入账户', amount DECIMAL(20,2) NOT NULL COMMENT '转账金额', currency VARCHAR(3) NOT NULL COMMENT '货币', status TINYINT NOT NULL DEFAULT 0 COMMENT '状态:0处理中,1成功,2失败', fail_reason VARCHAR(255) COMMENT '失败原因', remark VARCHAR(255) COMMENT '备注', create_time DATETIME DEFAULT CURRENT_TIMESTAMP, finish_time DATETIME COMMENT '完成时间', INDEX idx_status_time (status, create_time), INDEX idx_from_account (from_account_no, create_time), INDEX idx_to_account (to_account_no, create_time) ) ENGINE=InnoDB COMMENT='转账记录表';3. 核心代码实现3.1 转账服务接口// 转账请求DTO @Data public class TransferRequest { @NotBlank private String fromAccountNo; @NotBlank private String toAccountNo; @DecimalMin(value = "0.01", message = "转账金额必须大于0") private BigDecimal amount; @NotBlank private String currency; private String remark; @NotBlank private String requestId; // 请求ID,用于幂等性 } // 转账服务接口 public interface TransferService { /** * 同步转账 */ TransferResult transfer(TransferRequest request); /** * 异步转账 */ CompletableFutureTransferResult transferAsync(TransferRequest request); /** * 批量转账 */ BatchTransferResult batchTransfer(ListTransferRequest requests); }3.2 账户服务实现@Service @Slf4j public class AccountServiceImpl implements AccountService { @Autowired private AccountMapper accountMapper; @Autowired private RedisTemplateString, Object redisTemplate; @Autowired private RedissonClient redissonClient; // 账户本地缓存 private final CacheString, Account accountCache = Caffeine.newBuilder() .maximumSize(10000) .expireAfterWrite(5, TimeUnit.SECONDS) .build(); @Override @Transactional(rollbackFor = Exception.class) public Account getAccountForUpdate(String accountNo) { String lockKey = "account_lock:" + accountNo; RLock lock = redissonClient.getLock(lockKey); try { // 加锁,防止并发操作同一账户 boolean locked = lock.tryLock(3, 10, TimeUnit.SECONDS); if (!locked) { throw new ServiceException("系统繁忙,请稍后重试"); } // 从缓存获取 Account account = accountCache.getIfPresent(accountNo); if (account == null) { // 从数据库获取并加行锁 account = accountMapper.selectForUpdate