11 KiB
业务后端数据库初版方案
文档版本:v1.0 最后更新:2026-04-02 08:28:05
1. 目标
本文档定义本项目业务后端第一版数据库方案。
第一版目标不是一次性覆盖整个平台所有能力,而是先稳定支撑以下范围:
- 微信小程序登录与用户身份
- 用户身体资料
- 多租户与俱乐部基础隔离
- 首页卡片、赛事、地图、Event 查询
- 配置对象的版本化管理与发布
launch启动与session_token- 小程序业务层与配置驱动游戏层对接
明确不纳入第一版数据库的能力:
- 支付与分账
- UGC 审核流
- 订单退款
- 成绩回放明细
- GPS / 心率明细归档
- 复杂运营报表
这些能力建议放到后续 migration。
2. 核心原则
2.1 业务数据与配置数据分层
数据库里同时存在两类对象:
- 业务状态对象
- 配置发布对象
两者要分层,不要揉成一个“超级事件表”。
2.2 运行态配置仍然走发布产物
数据库管理的是编辑态与发布关系,客户端运行时最终仍然消费静态发布结果,例如:
manifest_urlmanifest_checksum_sha256- 地图资源路径
- Event 发布配置
不要让客户端在运行时直接拼数据库对象。
2.3 游戏规则不进业务表细字段
业务后端负责:
- 用户
- 赛事
- 报名
- 发布
- 启动
业务后端不应该成为所有玩法字段的解释器。玩法细节优先放在版本化 jsonb 内容中。
2.4 所有对外 ID 使用 public_id
数据库内部主键统一使用 uuid。
对客户端暴露的对象使用稳定 public_id:
user_public_idcompetition_public_idmap_public_idevent_public_idrelease_public_idsession_public_id
原因:
- 内外 ID 解耦
- 便于迁移
- 便于白标和多端统一
- 避免顺序 ID 暴露内部增长信息
2.5 token 只存 hash,不存明文
以下内容不应明文入库:
- 短信验证码
- refresh token
- session token
数据库只保存 hash。
3. 第一版建议模块
第一版数据库建议拆成 6 组:
- 租户与组织
- 用户与登录
- 配置对象与发布
- 赛事业务对象
- 页面与卡片
- 启动与 session
4. 表清单
4.1 租户与组织
tenants
平台租户。
建议字段:
idtenant_codenamestatustheme_jsonbsettings_jsonbcreated_atupdated_at
说明:
theme_jsonb存白标主题settings_jsonb存租户级开关
clubs
租户下的俱乐部或品牌实体。
建议字段:
idtenant_idclub_codenamestatusprofile_jsonbcreated_atupdated_at
说明:
- 第一版建议 club 从属于 tenant
- 不建议一开始做过深的组织树
4.2 用户与登录
app_users
平台用户主表。
建议字段:
iduser_public_iddefault_tenant_idstatusnicknameavatar_urllast_login_atcreated_atupdated_at
login_identities
登录身份绑定表。
建议字段:
iduser_ididentity_typeproviderprovider_subjectcountry_codemobilestatusprofile_jsonbcreated_atupdated_at
身份示例:
- 手机号
- 微信
openid - 微信
unionid
client_devices
客户端设备标识记录。
建议字段:
iddevice_keyplatformfirst_seen_atlast_seen_atmeta_jsonb
说明:
device_key对应前端device_id
auth_sms_codes
短信验证码发送与校验记录。
建议字段:
idscenecountry_codemobileclient_typedevice_keycode_hashprovider_payload_jsonbexpires_atcooldown_untilconsumed_atcreated_at
auth_refresh_tokens
刷新 token 持久化表。
建议字段:
iduser_idclient_typedevice_keytoken_hashissued_atexpires_atrevoked_atreplaced_by_token_id
user_body_profiles
用户当前身体档案。
建议字段:
iduser_idstatuscompleted_atcurrent_version_idcreated_atupdated_at
user_body_profile_versions
身体档案历史版本。
建议字段:
idprofile_idversion_nogenderbirth_dateheight_cmweight_kgresting_heart_rate_bpmmax_heart_rate_bpmcreated_at
4.3 配置对象与发布
这一组直接对应你现有的配置驱动架构。
maps / map_versions
地图对象及版本。
主表管理:
map_public_idslugnamestatustenant_idcurrent_version_id
版本表管理:
version_nocontent_jsonbcreated_at
playfields / playfield_versions
路线、点位、场地定义。
game_modes / game_mode_versions
玩法模式配置,例如:
classic-sequentialscore-o
resource_packs / resource_pack_versions
资源包,例如:
- 音效
- 素材包
- UI 资源集
events / event_versions
Event 本身与版本。
建议:
events管对象身份event_versions管编辑态装配结果
event_versions 推荐显式引用:
map_version_idplayfield_version_idgame_mode_version_idresource_pack_version_id
同时保留:
content_jsonb
这样既有强关系,又保留灵活字段。
event_releases
发布记录表。
建议字段:
idrelease_public_idevent_idevent_version_idrelease_nomanifest_urlmanifest_checksum_sha256statuspublished_by_user_idpublished_atpayload_jsonb
说明:
- 客户端主要读这张表产出的 URL 与校验值
events.current_release_id可指向当前对外生效版本
4.4 赛事业务对象
competitions
赛事主表。
建议字段:
idcompetition_public_idtenant_idclub_idslugdisplay_namestatusregistration_enabledleaderboard_enabledrealtime_board_enabledcompetition_start_atcompetition_end_atcontent_jsonbcreated_atupdated_at
competition_events
赛事与 Event 的关联表。
建议字段:
idcompetition_idevent_idevent_release_idis_defaultsort_orderrelation_statuscreated_at
说明:
- 支持赛事绑定多个 Event
- 支持按赛事锁定某个 release
registrations
报名记录。
建议字段:
idregistration_public_idcompetition_iduser_idgroup_idstatusform_payload_jsonbapproved_atcancelled_atcreated_atupdated_at
说明:
- 第一版先不强行拆复杂参赛人结构
form_payload_jsonb足够承接早期变化
4.5 页面与卡片
page_configs / page_config_versions
H5 / 白标页面配置。
主表建议字段:
idtenant_idclub_idpage_codenamestatuscurrent_version_idcreated_atupdated_at
版本表建议字段:
idpage_config_idversion_nodsl_jsonbtheme_jsonbfeature_flags_jsonbstatuscreated_at
cards
首页卡片与运营入口。
建议字段:
idcard_public_idtenant_idclub_idcard_typedisplay_namecompetition_idevent_idmap_idpage_config_idhtml_urlcover_urldisplay_slotdisplay_prioritystatusstarts_atends_atcreated_atupdated_at
说明:
- 这张表直接支撑
/cards - 允许卡片指向赛事、页面或其他目标
4.6 启动与 session
game_sessions
游戏启动记录。
建议字段:
idsession_public_idtenant_iduser_idcompetition_idregistration_idevent_idevent_release_idlaunch_request_idparticipant_public_iddevice_keyclient_typeroute_codestatussession_token_hashsession_token_expires_atrealtime_endpointrealtime_token_hashlaunched_atstarted_atended_atcreated_atupdated_at
说明:
- 第一版闭环到
launch即可 session_token用于后续 session 相关接口开放后继续扩展launch_request_id需要唯一,支撑幂等
5. 当前 API 到表的映射
POST /auth/sms/send
写:
auth_sms_codes
POST /auth/login/sms
读写:
auth_sms_codesapp_userslogin_identitiesuser_body_profilesuser_body_profile_versionsauth_refresh_tokens
POST /auth/login/wechat
读写:
app_userslogin_identitiesuser_body_profilesuser_body_profile_versionsauth_refresh_tokens
POST /auth/refresh
读写:
auth_refresh_tokens
PUT /me/body-profile
读写:
user_body_profilesuser_body_profile_versions
GET /cards
读:
cards- 可选补充
competitions
GET /competitions/{competition_id}
读:
competitionscompetition_eventseventsevent_releasesregistrations
GET /events/{event_id} / GET /competitions/{competition_id}/events/{event_id}
读:
eventsevent_releasesmapscompetitionsregistrations
POST /competitions/{competition_id}/registrations
写:
registrations
POST /events/{event_id}/launch
读写:
eventsevent_releasesregistrations可选game_sessions
6. 第一版不建议做复杂拆分的地方
以下字段第一版优先用 jsonb,不要先做一堆子表:
- 赛事详情扩展内容
- 报名附加表单
- 页面 DSL
- theme 配置
- feature flags
- Event 覆盖项
- 配置对象的实验字段
原因很简单:
- 你现在业务和玩法都在快速变化
- 先保留灵活性比过度范式化更重要
7. 第一版不建议进入数据库的内容
第一版不建议落库:
- 实时网关运行态内存结构
- GPS 点逐秒明细
- 心率逐秒明细
- WebGL 渲染状态
- 设备桥接瞬时事件
这些应该仍然留在:
realtime-gateway- 对象存储
- 后续归档服务
不应直接压进业务主库。
8. 推荐 migration 顺序
建议按下面顺序建表:
- 租户与组织
- 用户与登录
- 配置对象与版本表
- 发布表
- 赛事与关联
- 页面与卡片
- session
这样依赖关系最清晰。
9. 第二版可新增的模块
建议后续 migration 再补:
orderspayment_transactionsrefundsugc_assetsugc_postsugc_reviewssession_uploadssession_resultsgps_tracksheart_rate_streamschannel_entriescampaigns
10. 当前最适合你的起步方式
如果你现在准备开始做后端,我建议不要先写所有 API,而是按这个顺序开工:
- 先建数据库与 migration
- 先写用户、赛事、Event、launch 这 4 个核心域
- 先让小程序跑通登录 -> 看赛事 -> launch -> 进入游戏
- 再补报名
- 再补页面配置、卡片、俱乐部首页
- 支付和 UGC 放到后续版本
11. 一句话总结
第一版数据库应该同时支撑两件事:
- 业务闭环
- 配置发布
但不能把它们混成一套随意增长的表结构。
正确方向是:
PostgreSQL 存业务状态 + 版本化配置对象,Go API 负责查询与发布编排,客户端继续消费发布后的运行态配置。