flat-server数据库设计:用户、房间与云存储表结构深度解析
2026/8/5 21:32:51 网站建设 项目流程

flat-server数据库设计:用户、房间与云存储表结构深度解析

【免费下载链接】flat-serverA Node.js server for the Agora Flat open source classroom.项目地址: https://gitcode.com/gh_mirrors/fl/flat-server

flat-server作为Agora Flat开源教室的核心后端服务,其数据库设计直接影响系统的稳定性与扩展性。本文将深度解析用户管理、房间控制和云存储三大核心模块的表结构设计,揭示如何通过合理的表结构实现百万级用户的在线教学场景支持。

用户管理模块:身份体系的基石

用户模块采用主表+关联表的设计模式,通过users主表存储核心身份信息,配合第三方登录关联表实现多平台账号统一管理。

用户核心表(users)

users表作为用户体系的核心,存储了最关键的身份标识与基础信息:

@Entity({ name: "users" }) export class UserModel extends Content { @Index("users_user_uuid_uindex", { unique: true }) @Column({ length: 40 }) user_uuid: string; // 用户唯一标识 @Column({ length: 50 }) user_name: string; // 用户名 @Column({ precision: 32 }) user_password: string; // 密码哈希 @Column({ length: 2083 }) avatar_url: string; // 头像URL @Column({ type: "enum", enum: [Gender.Man, Gender.Woman, Gender.None], default: Gender.None }) gender: Gender; // 性别 @Index("users_is_blacklist_index") @Column({ default: false }) is_blacklist: boolean; // 是否黑名单用户 }

核心设计亮点:

  • 使用user_uuid作为业务主键,避免自增ID暴露用户数量
  • 通过is_blacklist字段实现基础封禁功能,配合user_blacklist表实现完整封禁体系
  • 索引设计兼顾查询效率与唯一性约束,如users_user_uuid_uindex确保用户UUID不重复

用户黑名单表(user_blacklist)

该表存储详细的用户封禁记录,支持多维度封禁策略:

CREATE TABLE `user_blacklist` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `user_uuid` VARCHAR(40) NULL DEFAULT NULL COMMENT '被封禁用户UUID', `phone_number` VARCHAR(50) NULL DEFAULT NULL COMMENT '被封禁手机号', `email` VARCHAR(100) NULL DEFAULT NULL COMMENT '被封禁邮箱', `reason` VARCHAR(255) NULL DEFAULT NULL COMMENT '封禁原因', `operator` VARCHAR(40) NULL DEFAULT NULL COMMENT '操作人', `is_delete` TINYINT(1) NOT NULL DEFAULT 0, `created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), `updated_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), PRIMARY KEY (`id`), INDEX `user_blacklist_user_uuid_index` (`user_uuid`), UNIQUE INDEX `user_blacklist_phone_uindex` (`phone_number`), UNIQUE INDEX `user_blacklist_email_uindex` (`email`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户黑名单';

设计特点:

  • 支持通过UUID、手机号、邮箱三种方式封禁用户
  • 手机号和邮箱设置唯一索引,防止重复封禁
  • 保留操作人信息,满足审计需求

第三方登录关联表

系统支持多种登录方式,每种方式对应独立的关联表,如:

  • Agora登录关联表
  • 微信登录关联表
  • GitHub登录关联表

以微信登录关联表为例:

@Entity({ name: "user_wechat" }) export class UserWeChatModel extends Content { @Index("user_wechat_open_id_uindex", { unique: true }) @Column({ length: 64 }) open_id: string; // 微信开放平台ID @Column({ length: 40 }) user_uuid: string; // 关联的用户UUID }

这种设计既保证了数据隔离,又通过user_uuid实现了多账号的统一关联。

房间管理模块:在线教学的核心载体

房间模块采用"主房间+周期性房间+房间用户"的三级结构,灵活支持单次课程与系列课程两种教学模式。

房间主表(rooms)

rooms表存储单次课程的核心信息:

@Entity({ name: "rooms" }) export class RoomModel extends Content { @Index("rooms_room_uuid_uindex", { unique: true }) @Column({ length: 40 }) room_uuid: string; // 房间唯一标识 @Index("rooms_periodic_uuid_index") @Column({ length: 40 }) periodic_uuid: string; // 周期性房间UUID(如为系列课程) @Index("rooms_owner_uuid_index") @Column({ length: 40 }) owner_uuid: string; // 房间创建者UUID @Column({ length: 150 }) title: string; // 房间标题 @Index("rooms_room_type_index") @Column({ type: "enum", enum: [RoomType.OneToOne, RoomType.BigClass, RoomType.SmallClass] }) room_type: RoomType; // 房间类型(一对一/大班课/小班课) @Index("rooms_room_status_index") @Column({ type: "enum", enum: [RoomStatus.Idle, RoomStatus.Started, RoomStatus.Paused, RoomStatus.Stopped] }) room_status: RoomStatus; // 房间状态 @Index("rooms_begin_time_index") @Column({ type: "datetime", precision: 3 }) begin_time: Date; // 开始时间 @Column({ type: "datetime", precision: 3 }) end_time: Date; // 结束时间 @Column({ type: "enum", enum: [Region.CN_HZ, Region.US_SV, Region.SG, Region.IN_MUM, Region.GB_LON] }) region: Region; // 服务器区域 @Index("rooms_whiteboard_room_uuid_uindex", { unique: true }) @Column({ length: 40 }) whiteboard_room_uuid: string; // 白板房间UUID }

关键设计考量:

  • 支持多区域部署,通过region字段实现就近接入
  • 房间状态流转清晰,支持Idle→Started→Paused→Stopped完整生命周期
  • 与白板服务深度集成,通过whiteboard_room_uuid建立关联

周期性房间表(room_periodic)

针对系列课程场景,设计了room_periodic表存储周期性课程信息:

@Entity({ name: "room_periodic" }) export class RoomPeriodicModel extends Content { @Index("room_periodic_periodic_uuid_uindex", { unique: true }) @Column({ length: 40 }) periodic_uuid: string; // 周期性房间唯一标识 @Column({ length: 40 }) owner_uuid: string; // 创建者UUID @Column({ length: 150 }) title: string; // 课程标题 @Column({ type: "json" }) config: PeriodicConfig; // 周期性配置(频率、周几等) }

配合RoomPeriodicConfig表和RoomPeriodicUser表,实现周期性课程的完整管理。

房间用户关联表(room_user)

该表记录用户与房间的关联关系,支持角色权限控制:

@Entity({ name: "room_user" }) export class RoomUserModel extends Content { @Index("room_user_room_uuid_index") @Column({ length: 40 }) room_uuid: string; // 房间UUID @Index("room_user_user_uuid_index") @Column({ length: 40 }) user_uuid: string; // 用户UUID @Column({ type: "enum", enum: [RoomUserRole.Owner, RoomUserRole.Admin, RoomUserRole.User] }) role: RoomUserRole; // 用户角色 @Column({ default: false }) is_camera_on: boolean; // 摄像头状态 @Column({ default: false }) is_microphone_on: boolean; // 麦克风状态 }

通过复合索引room_user_room_uuid_user_uuid_index确保用户在房间中的唯一性。

云存储模块:教学资源的管理中心

云存储模块采用"文件元数据+用户文件关联"的设计模式,支持多类型教学资源的存储与访问控制。

文件元数据表(cloud_storage_files)

cloud_storage_files表存储文件的核心元数据:

@Entity({ name: "cloud_storage_files" }) export class CloudStorageFilesModel extends Content { @Index("cloud_storage_files_file_uuid_uindex", { unique: true }) @Column({ length: 40 }) file_uuid: string; // 文件唯一标识 @Column({ length: 128 }) file_name: string; // 文件名 @Column({ unsigned: true, type: "int" }) file_size: number; // 文件大小(字节) @Column({ length: 256 }) file_url: string; // 文件访问URL @Column({ length: 300, default: "/" }) directory_path: string; // 目录路径 @Column({ type: "json", default: () => "('{}')" }) payload: FilePayload; // 文件额外信息(如转换状态、缩略图等) @Index("cloud_storage_files_resource_type_index") @Column({ length: 20, type: "varchar" }) resource_type: FileResourceType; // 文件类型 }

设计亮点:

  • 通过resource_type字段区分不同类型文件(如文档、视频、图片等)
  • payload字段使用JSON类型存储动态元数据,适应不同文件类型需求
  • 支持目录结构,通过directory_path实现文件组织

用户文件关联表(cloud_storage_user_files)

该表管理用户与文件的所有权关系:

@Entity({ name: "cloud_storage_user_files" }) export class CloudStorageUserFilesModel extends Content { @Index("cloud_storage_user_files_user_uuid_index") @Column({ length: 40 }) user_uuid: string; // 用户UUID @Index("cloud_storage_user_files_file_uuid_index") @Column({ length: 40 }) file_uuid: string; // 文件UUID @Index("cloud_storage_user_files_user_file_uindex", { unique: true }) @Column({ length: 40 }) user_file_uuid: string; // 用户文件唯一标识 }

通过user_file_uuid实现用户对同一文件的多次引用,节省存储空间。

表结构设计最佳实践总结

flat-server的数据库设计遵循以下原则,确保系统高效稳定运行:

  1. 业务主键设计:采用UUID作为业务主键,避免自增ID带来的安全风险与分库分表困难
  2. 索引优化:为所有查询条件和关联字段建立合适索引,如rooms_owner_uuid_index加速房间列表查询
  3. 软删除机制:通过is_delete字段实现逻辑删除,保留历史数据便于审计与恢复
  4. 多表关联:通过UUID建立表间关联,而非直接外键约束,提高系统灵活性
  5. 时间精度:所有时间字段采用DATETIME(3)类型,提供毫秒级时间精度
  6. 扩展字段:使用JSON类型字段(如payload)存储动态变化的元数据

这些设计决策使flat-server能够支持从几十人到上万人的在线教学场景,为Agora Flat开源教室提供坚实的数据基础。

数据库迁移与维护

项目提供完善的数据库迁移脚本,位于scripts/migration/目录下,每个迁移脚本都包含详细的变更说明和回滚方案。例如:

  • 用户黑名单迁移脚本
  • 管理员账号迁移脚本

建议定期执行yarn run sync-orm命令同步实体模型与数据库结构,确保开发与生产环境的表结构一致。

通过这套精心设计的数据库架构,flat-server实现了用户、房间、资源的高效管理,为在线教育场景提供了可靠的数据支撑。开发者可以基于这些表结构,快速扩展新功能或进行性能优化。

【免费下载链接】flat-serverA Node.js server for the Agora Flat open source classroom.项目地址: https://gitcode.com/gh_mirrors/fl/flat-server

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询