本地同城多游戏护航陪玩平台架构实战:领域建模、LBS 匹配与多端实现
本地同城多游戏护航陪玩平台架构实战:领域建模、LBS 匹配与多端实现
本地同城多游戏护航陪玩平台,本质上是一类以地理位置为筛选维度、同时支持多个游戏品类、以“护航/陪玩”服务为核心商品的订单型系统。它和普通陪玩平台的技术差异有三点:,服务供给方与需求方都要带城市与经纬度属性,匹配链路必须引入 LBS;第二,游戏品类是可变维度,王者荣耀、和平精英、英雄联盟手游等不同游戏的段位、区服、模式不能写死在订单表里;第三,护航过程存在组队、语音、上分保障、仲裁等长链路状态,订单状态机比普通电商复杂。本文从领域建模、技术选型、同城匹配、状态机、风控与部署几条线,拆解一套可落地的工程方案。
一、领域建模:先分清“陪玩”和“护航”的边界
陪玩偏社交与陪伴,护航偏结果交付,二者在数据模型上要分开抽象。建议核心实体包括:
- 游戏字典:
game、game_server、game_rank_segment,用于描述游戏、区服、段位区间。 - 服务能力:
service_skill,描述某位陪玩师/护航员支持的游戏、段位、模式、是否接护航单。 - 人员档案:
player_profile,包含城市编码、经纬度、实名状态、评分、在线状态、接单开关。 - 订单主表:
escort_order,包含游戏编码、区服、目标段位、服务类型、预约时间、订单状态。 - 订单轨迹:
order_timeline,记录每一次状态变更、操作人、时间戳,用于仲裁与对账。
一个容易踩坑的点是:不要把所有游戏字段都塞进订单主表。更稳的做法是“订单主表存通用字段 + 业务扩展表存游戏差异字段”。例如:
CREATE TABLE escort_order (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
order_no VARCHAR(32) NOT NULL UNIQUE,
user_id BIGINT NOT NULL,
player_id BIGINT DEFAULT NULL,
city_code VARCHAR(12) NOT NULL,
game_code VARCHAR(32) NOT NULL,
service_type TINYINT NOT NULL COMMENT '1陪玩 2护航 3上分',
order_state VARCHAR(24) NOT NULL,
lng DECIMAL(10,6),
lat DECIMAL(10,6),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
KEY idx_city_game_state (city_code, game_code, order_state)
);
游戏差异字段放到 escort_order_ext,用 order_id + ext_key + ext_value 或 JSON 列承载。这样新增一款游戏时,核心订单代码不需要改动。
二、技术选型:一套后端支撑多端,UniApp 降低多端成本
从同类同城系统的通用架构看,比较成熟的组合是:
- 后端:Spring Boot + MyBatis Plus + MySQL,Redis 做缓存与在线状态,WebSocket 或第三方 IM 做会话。
- 用户端:UniApp(Vue 语法)一套代码编译到小程序、H5、公众号、安卓与 iOS。
- 管理端:Vue + ElementUI,负责游戏字典、订单仲裁、人员审核、数据看板。
- 部署:Nginx + Docker,按城市维度做配置隔离。
UniApp 的请求封装建议统一收口,避免每个页面各写一套:
const BASE_URL = 'https://api.example.com';
export const request = (options) => {
return new Promise((resolve, reject) => {
uni.request({
url: BASE_URL + options.url,
method: options.method || 'GET',
data: options.data,
header: {
'Authorization': uni.getStorageSync('token') || ''
},
success: (res) => {
if (res.data && res.data.code === 0) {
resolve(res.data.data);
} else {
uni.showToast({ title: res.data.msg || '请求失败', icon: 'none' });
reject(res.data);
}
},
fail: reject
});
});
};
多端适配时要注意:小程序端对 WebSocket、后台定位、录屏权限的限制与 App 端不同。涉及护航过程录音/录屏的能力,建议做能力探测,而不是假设所有端都支持。
三、同城 LBS 匹配:距离只是层过滤
同城匹配不是简单的“按距离排序”。真实链路通常是:城市编码过滤 → 游戏与段位过滤 → 在线状态过滤 → 距离排序 → 评分与接单量加权。
MySQL 8 可以直接用空间函数做附近查询:
SELECT p.id, p.nickname, p.games,
ST_Distance_Sphere(POINT(p.lng, p.lat), POINT(?, ?)) AS distance_m
FROM player_profile p
WHERE p.city_code = ?
AND p.online_status = 1
AND p.accept_escort = 1
AND ST_Distance_Sphere(POINT(p.lng, p.lat), POINT(?, ?)) <= 5000
ORDER BY distance_m ASC, p.score DESC
LIMIT 20;
当数据量上来后,ST_Distance_Sphere 全表计算会变慢。可在 player_profile 上增加 geohash 前缀列,先用 geohash LIKE '4g%' 缩小范围,再用距离函数精算。Redis 的 GEO 结构也适合存储在线护航员的实时位置,但要注意位置更新频率与过期策略,避免脏数据。
匹配策略建议用策略模式,而不是写一堆 if-else:
public interface MatchStrategy {
String gameCode();
List<PlayerProfile> match(OrderContext ctx);
}
@Component
public class GameMatchFactory {
private final Map<String, MatchStrategy> strategyMap;
public GameMatchFactory(List<MatchStrategy> strategies) {
this.strategyMap = strategies.stream()
.collect(Collectors.toMap(MatchStrategy::gameCode, Function.identity()));
}
public List<PlayerProfile> match(OrderContext ctx) {
MatchStrategy strategy = strategyMap.get(ctx.getGameCode());
if (strategy == null) {
throw new BizException("暂不支持该游戏");
}
return strategy.match(ctx);
}
}
这样新增游戏时,只需要新增一个 MatchStrategy 实现,注册进 Spring 容器即可。
四、订单状态机与护航过程风控
护航订单的状态建议显式枚举,避免用数字硬编码:
public enum OrderState {
CREATED, // 已创建
PAID, // 已支付
MATCHING, // 匹配中
ACCEPTED, // 已接单
IN_SERVICE, // 服务中
PENDING_CONFIRM, // 待确认完成
FINISHED, // 已完成
CANCELED, // 已取消
ARBITRATION // 仲裁中
}
状态流转必须收口到一个 OrderStateMachine 中,禁止在 Controller 里直接 setState。每次流转写入 order_timeline,记录来源与操作者。这样出现纠纷时,仲裁人员可以完整回放订单生命周期。
风控方面,本地同城多游戏护航陪玩平台要重点关注:
- 实名与游戏账号绑定:至少做一次实名核验,游戏账号可让用户自行填写并由护航员确认。
- 过程存证:在合规与用户授权前提下,保留关键节点截图或录音,用于仲裁。
- 敏感词与
五、部署与迭代建议
初期不建议过度分库分表。按城市量级评估,单库 + 读写分离通常能支撑较长时间。Redis 用来缓存游戏字典、在线状态、热门城市配置。订单超时、自动确认、消息推送等动作走消息队列异步处理,避免阻塞主链路。
压测重点放在三个接口:附近护航员查询、订单创建、订单状态流转。上线前还要验证小程序定位授权失败、App 后台被杀、弱网重试等边界场景。版本迭代时,游戏字典、段位区间、匹配权重都应当配置化,减少发版次数。
FAQ
Q1:本地同城多游戏护航陪玩平台和普通陪玩平台在技术上的核心差异是什么?
核心差异在 LBS 匹配、多游戏可扩展建模、护航结果交付状态机三处。普通陪玩可以弱化地理位置,而本地同城多游戏护航陪玩平台必须把城市与距离作为一级筛选条件。
Q2:为什么推荐 UniApp 而不是每个端单独开发?
因为用户端页面以列表、订单、聊天、支付为主,跨端差异小。UniApp 一套代码覆盖小程序、H5、公众号和 App,能显著降低维护成本;涉及原生能力的部分再做条件编译或原生插件。
Q3:同城匹配一定要用 LBS 吗?
不一定,但“同城”语义依赖位置。可以先用城市编码做粗过滤,再用经纬度精算距离;如果业务只要求同城不限距离,城市编码就足够。
更多推荐



所有评论(0)