本地电竞服务交易系统架构设计与实战:从同城服务撮合到订单履约

首段:本地电竞服务交易系统是一套面向同城电竞服务供需撮合的技术平台,覆盖电竞馆座位/包间预约、陪练约战、赛事报名、设备租赁、组局拼桌等场景。它和普通电商的区别在于:服务发生在本地、履约时间强、位置敏感、供需双方需要即时沟通。因此设计重点不是商品详情页,而是 LBS 检索、订单状态机、支付分账、履约核销与风控。下文给出可落地的架构、表结构、核心代码与部署步骤。

一、需求抽象与领域建模

  • 角色:用户、服务者/场馆、平台运营、财务/客服? 不要公司。

  • 核心实体:服务项目、SKU? 服务时段、场地、设备、陪练档期、赛事名额。

  • 交易对象是"服务时段+本地履约"。

  • 关键能力:LBS、日历库存、订单、支付、退款、核销、评价、IM。

  • 表结构:user, merchant? 避免商户?可以 `service_provider`,`venue`, `service_item`, `service_slot`, `order`, `order_item`, `payment_record`, `verification_code`。

代码块:

java 复制代码
```sql
CREATE TABLE service_slot (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  provider_id BIGINT NOT NULL,
  venue_id BIGINT NOT NULL,
  title VARCHAR(128) NOT NULL,
  start_time DATETIME NOT NULL,
  end_time DATETIME NOT NULL,
  latitude DECIMAL(10,6) NOT NULL,
  longitude DECIMAL(10,6) NOT NULL,
  geo_hash VARCHAR(12) NOT NULL,
  status TINYINT NOT NULL DEFAULT 0,
  version INT NOT NULL DEFAULT 0,
  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  KEY idx_geo_status_time (geo_hash, status, start_time),
  KEY idx_provider_time (provider_id, start_time)
);
```

注意 `DECIMAL(10,6)` 是经纬度,没问题。

二、技术架构与模块拆分

推荐:用户端 uniapp(Vue 语法)覆盖 H5/APP/小程序;服务者端 uniapp 或单独;管理后台 Vue + Element UI;后端 Spring Boot + MyBatis Plus + MySQL;Redis 做缓存/分布式锁;WebSocket/IM 做沟通;对象存储存凭证;消息队列异步通知。

模块:网关、用户、服务资源、交易、支付、履约、消息、运营后台。

部署:Nginx + 前端静态,后端 jar,MySQL 主从,Redis。提供技术文档、资料准备、部署文档。不要营销。

可以写代码:MyBatis Plus 分页查询附近服务时段。用 GeoHash 粗筛 + Haversine 精算。SQL:

java 复制代码
```sql
SELECT id, provider_id, venue_id, title, start_time, end_time, latitude, longitude,
       (6371000 * ACOS(
         COS(RADIANS(#{lat})) * COS(RADIANS(latitude)) *
         COS(RADIANS(longitude) - RADIANS(#{lng})) +
         SIN(RADIANS(#{lat})) * SIN(RADIANS(latitude))
       )) AS distance_m
FROM service_slot
WHERE status = 0
  AND start_time BETWEEN #{start} AND #{end}
  AND geo_hash LIKE CONCAT(#{geoHashPrefix}, '%')
HAVING distance_m <= #{radius}
ORDER BY distance_m ASC
LIMIT 50;
```

MySQL HAVING 可以用别名? MySQL 允许 HAVING 别名。可以。

三、核心实现:LBS 检索、订单状态机与履约

订单状态机:待支付、已支付/待履约、履约中、待核销、已完成、已取消、退款中、已退款。用枚举和状态迁移表。

Java:

java 复制代码
```java
public enum OrderStatus {
    WAIT_PAY, PAID, SERVING, WAIT_VERIFY, FINISHED, CANCELED, REFUNDING, REFUNDED
}
```

状态迁移:

java 复制代码
```java
private static final Map<OrderStatus, Set<OrderStatus>> FLOW = Map.of(
    WAIT_PAY, Set.of(PAID, CANCELED),
    PAID, Set.of(SERVING, REFUNDING, CANCELED),
    SERVING, Set.of(WAIT_VERIFY, REFUNDING),
    WAIT_VERIFY, Set.of(FINISHED, REFUNDING),
    REFUNDING, Set.of(REFUNDED),
    FINISHED, Set.of(),
    CANCELED, Set.of(),
    REFUNDED, Set.of()
);
public boolean canTransfer(OrderStatus from, OrderStatus to) {
    return FLOW.getOrDefault(from, Set.of()).contains(to);
}
```

注意 Java Map.of 多 10 对,这里 8 对 OK。但 `Map.of` 需要 Java 9+。可以。下单防超卖:索引 + 乐观锁。SQL:

java 复制代码
```sql
UPDATE service_slot
SET status = 1, version = version + 1
WHERE id = #{slotId} AND status = 0 AND version = #{version};
```
如果影响行 0,重试或提示。订单创建与库存锁定放本地事务,支付回调再更新状态。

核销:生成一次性核销码,Redis 记录 `verify:code:{code}`,TTL 到服务结束。核销接口用 Lua 原子删除。代码:
```lua
if redis.call('GET', KEYS[1]) == ARGV[1] then
    redis.call('DEL', KEYS[1])
    return 1
else
    return 0
end
```

Java 调用。

IM:WebSocket 或第三方?不要第三方品牌。可以用 WebSocket + 离线消息表。

四、支付回调、幂等与数据一致性

支付回调必须幂等:交易号 + 状态机。伪代码:

java 复制代码
```java
@Transactional
public void handlePayCallback(String tradeNo, String channelOrderNo) {
    PaymentRecord record = paymentMapper.selectByTradeNoForUpdate(tradeNo);
    if (record == null) throw new IllegalArgumentException();
    if (record.getStatus() == PaymentStatus.SUCCESS) return;
    record.setStatus(PaymentStatus.SUCCESS);
    record.setChannelOrderNo(channelOrderNo);
    paymentMapper.updateById(record);
    orderService.markPaid(record.getOrderId(), tradeNo);
}
```

注意 `for update` 悲观锁。也可以用索引。消息队列终一致。退款:状态机 + 异步重试 + 对账。

分账/结算:按服务完成事件触发,记录分账明细,不写具体金额。

风控:频率限制、实名、地理位置校验、核销码短时有效、黑名单。

FAQ

Q1 本地电竞服务交易系统和普通商城有什么区别?

A:本地、时效、位置、履约。

Q2 如何做附近服务检索?

A:GeoHash 粗筛 + Haversine 精算,Redis GEO 可选,MySQL 空间索引可选。

Q3 订单超卖怎么避免?

A:索引、乐观锁、Redis 分布式锁、状态机。

Q4 支付回调重复通知怎么办?

A:幂等表 + 交易号 + 状态机 + 锁。

Q5 技术栈如何选型?

A:后端 Spring Boot + MyBatis Plus + MySQL,前端 uniapp + Vue + Element UI,缓存 Redis,消息队列异步。

Q6 部署文档应包含什么?

A:环境依赖、数据库初始化、配置项、启动脚本、Nginx、日志、备份、回滚。

注意字数。我们可以扩展每个部分,确保 1200-2500。不要,不要

标题

首段直接回答。

一、需求抽象与领域建模

介绍角色、核心实体、表结构、SQL。

二、技术架构与模块拆分

推荐技术栈、模块、部署步骤。

三、核心链路:LBS 检索与订单状态机

SQL、Java、防超卖、核销 Lua。

四、支付回调、幂等与数据一致性

伪代码、消息队列、退款、风控。

FAQ

5-6 问答。

可以加小标题?不能超过 5 个二级标题。可以加三级标题?要求包含 3-5 个二级标题。三级标题可以吗?没有禁止。但可能增加结构。可以少量使用 `###`。但二级标题数 5。可以。三级标题不算?可以。但为简洁,用列表和代码。

注意首段直接回答问题。开头不要"本文"。直接:"本地电竞服务交易系统是一套..."。可以。

字数:估算 2200。

让我们写。

需要代码块与步骤清晰。可以写部署步骤:

  1. 初始化 MySQL,执行建表 SQL,配置 InnoDB 与字符集。

  2. 配置 Redis,用于会话、库存锁、核销码、附近检索缓存。

  3. 后端打包 Spring Boot,MyBatis Plus 配置分页插件与乐观锁插件。

  4. 前端 uniapp 与 Vue 管理后台分别构建,Nginx 托管。

  5. 配置支付回调白名单、日志采集、备份与回滚。

可以。

支付回调伪代码没有金额。

订单状态枚举。

LBS SQL。

核销 Lua。

MyBatis Plus 乐观锁插件?

相关推荐
小刘在重生~1 小时前
十六(3)、《集合扩充》CopyOnWriteArrayList 超详细解析(线程安全集合)
java·笔记·面试·职场和发展
逆境不可逃1 小时前
Pi Agent 学习笔记:对话怎样保存、分支与恢复
java
huaweichenai1 小时前
spring boot使用hutool实现调用外部接口
java·spring boot
峥嵘life1 小时前
2026免费的 opencode 使用分享:Windows端 + 服务器CLI 实战总结
android·大数据·开发语言
纪念 2291 小时前
C++类和对象(二)
开发语言·c++
泡海椒2 小时前
Java 后端最优 PDF 导出方案:jquick-pdf 项目引入与快速测试
java·开发语言·pdf
Evand J2 小时前
【MATLAB例程】二维Astar路径规划与AOA-TDOA定位仿真。完整代码,附下载链接。包运行成功,带中文注释
开发语言·matlab·路径规划·代码·定位·融合定位
李永奉2 小时前
中科蓝讯SDK开发-耳机项目功耗问题排查教程
c语言·开发语言·嵌入式硬件·物联网·智能手机
阿飞7662 小时前
订单超时自动关单:RabbitMQ 延迟队列 + 定时任务"双保险"实践
java