Skip to content

数据库设计 ​

数据库使用 PostgreSQL + GORM,迁移由 migrate 角色(migrations.AutoMigrate)统一执行。所有表按业务域组织,实体定义在 internal/model/entity/。

ER 总览(按业务域) ​

text
┌── 用户与权限域 ──┐   ┌── 视频域 ──┐   ┌── 社交互动域 ──┐
│ users            │   │ videos     │   │ video_comments │
│ user_profiles    │   │ video_sources│  │ video_likes    │
│ roles            │   │ video_transcodes│ video_favorites │
│ authorities      │   │ video_manifest│ │ video_play_logs│
│ role_authority   │   │ tags        │   │ comment_likes  │
│ user_authority   │   │ video_tags  │   └────────────────┘
└──────────────────┘   └────────────┘
┌── 文件域 ──┐   ┌── 弹幕域 ──┐   ┌── 其他 ──┐
│ files      │   │ danmaku    │   │ audit_logs│
│            │   │ sensitive_words │ └──────────┘
└────────────┘   └────────────┘

用户与权限 ​

表说明关键列
users用户主表id、username、password(bcrypt)、email、status、role
user_profiles用户扩展资料user_id、nickname、avatar
roles角色表code(如 admin/user)、name
authorities权限点resource(资源方法)、uri(资源路径)
role_authority角色-权限关联role_id、authority_id(联合主键)
user_authority用户-权限直接关联user_id、authority_id

文件管理 ​

表说明关键列
files通用文件表bucket、object_key、ref_type(视频原片/封面/manifest/评论附件)、size、mime_type、ref_count(引用计数)、status

files 是统一的对象引用表:原片、封面、DASH manifest、评论附件全部登记于此,支持引用计数(秒传去重依据)。

视频域 ​

表说明关键列
videos视频主表title、description、cover_file_id、duration、status(uploading/processing/published/failed)、visibility、like_count / favorite_count / play_count(冗余计数)
video_sources原始视频上传记录video_id、file_id、uploaded_at
video_transcodes转码任务与状态video_id、status(pending/processing/completed/failed)、resolution、codec、manifest_file_id;索引 (status, updated_at, video_id) 供 watchdog 扫描
video_manifest播放清单video_id、protocol(dash)、file_id、profiles(档位 JSON)
tags / video_tags标签及视频-标签多对多-

为什么 videos 冗余计数列? 列表页高频展示三计数,直接读 videos 列避免 join 明细表;明细表(video_likes 等)只做持久化审计与去重。

社交互动域 ​

表说明关键列
video_comments评论video_id、user_id、parent_id(父子结构)、content、status
video_likes点赞明细video_id、user_id(复合主键)
video_favorites收藏明细video_id、user_id(复合主键)
video_play_logs播放日志video_id、user_id、ip、user_agent、played_at
comment_likes评论点赞comment_id、user_id

明细表与 Redis 的关系:

计数Redis 实时DB 持久化
点赞interaction:like:{videoID}(Set 去重)video_likes + videos.like_count
收藏interaction:fav:{videoID}(Set 去重)video_favorites + videos.favorite_count
播放interaction:play:{videoID}(INCR)video_play_logs + videos.play_count

弹幕域 ​

表说明关键列
danmaku弹幕video_id、user_id、content、time_offset(时间轴位置)、color、mode
sensitive_words敏感词库word(AC 自动机加载)

审计 ​

表说明
audit_logs操作审计日志(预留)

设计要点 ​

  1. 复合主键做幂等:video_likes / video_favorites 用 (video_id, user_id) 复合主键,Flusher 幂等落库天然去重;
  2. 状态机驱动:videos.status 与 video_transcodes.status 构成转码流水线的状态机,配合 Redis 租约实现分布式幂等;
  3. 冗余计数列:展示读 videos 冗余列,明细表只增不改,避免热点行更新;
  4. 索引支撑 Watchdog:(status, updated_at, video_id) 索引让超时扫描走索引;
  5. 单库共享:当前所有服务共享 PostgreSQL,按「服务只读写自己归属的表集合」划分,跨服务用 ID 引用 + 事件/API(详见架构演进文档)。

迁移管理 ​

bash
# 手动执行迁移
go run ./cmd/vistack migrate

多副本部署时,建议将迁移作为独立一次性任务执行(K8s Job / compose run once),避免多实例同时 AutoMigrate 竞争。

基于 MIT License 发布