GGTalk 开源即时通讯系统源码剖析之:数据库设计

自从《开源即时通讯GGTalk 8.0发布,增加Linux客户端,支持在统信UOS、银河麒麟上运行!》一文在博客园发布后,有园友联系我QQ,说能不能整理个更系统更详细地介绍GGTalk源码的文章,现在博客中的介绍比较零散,对于初级程序员而言,面对GGTalk大量的源码,有点不知所措。想想也是如此,于是,我打算写一个系列的文章来完整地介绍GGTalk的方方面面,专题的名字就叫做《GGTalk源码剖析》吧。

一. 概述

这个《GGTalk源码剖析》系列的文章将基于最新的 GGTalk V8.0 进行。
GGTalk V8.0 服务端支持Windows、Linux,客户端支持 Windows、Android、iOS、Linux、以及银河麒麟、统信UOS等国产操作系统。
数据库支持SqlServer、MySql、以及达梦数据库、人大金仓、南大通用等国产数据库。本篇文章以 MySQL 数据库为例来对GGTalk的数据库设计进行详细的介绍。
还没有GGTalk源码的朋友,可以到 GGTalk源码下载中心 下载。

二. 数据表的设计

最新版本的 GGTalk 数据库一共涉及到九张表,分别为:

  • GGUser:用户表,所有注册用户都保存在该表中。
  • GGGroup:群组表,所有创建的群都保存在该表中。
  • OfflineMessage:离线消息表,当目标用户不在线时,发送给他的消息存在该表中。
  • OfflineFileItem:离线文件表,当目标用户不在线时,发送给他的文件对应的记录存在该表中。
  • GroupBan:群禁言表,当群中的用户被禁言时,对应的记录将存在该表中。
  • ChatMessageRecord:聊天记录表,一对一的聊天记录、群聊天记录都存在该表中。
  • AddFriendRequest:加好友请求表,所有添加好友的请求消息都存在该表中。
  • AddGroupRequest:入群请求表,所有申请入群的请求消息都存在该表中。
  • GGConfiguration:配置表,用于预留存储与GGTalk相关的配置信息。

下面将分别对每一张表的字段进行说明。

1. GGUser(用户表)

所有注册用户都保存在该表中。

字段名称 字段类型 字段说明
UserID varchar(50) 用户ID,主键
PasswordMD5 varchar(100) 经过加密处理的用户密码
Phone varchar(20) 用户手机号码
Name varchar(50) 用户昵称
Friends varchar(4000) 用户好友列表,以 , 分隔
CommentNames varchar(4000) 用户好友备注列表,以 ; 分隔
Signature varchar(100) 用户个性签名
HeadImageIndex int 系统默认头像的索引
HeadImageData mediumblob 用户上传头像的二进制数据
Groups varchar(1000) 用户所在的群组列表,以 , 分隔
UserState int 用户状态:0正常,1冻结,2禁言,3停用
MobileOfflineTime datetime 移动端离线的时间节点
PcOfflineTime datetime PC端离线的时间节点
CreateTime datetime 用户注册的时间节点
Version int 用户版本

补充说明:

  • UserId同时也是 用户账号用户名
  • Friends 字段中包含分组信息,每个分组之间以;进行分割。例如:朋友:friend1,friend2;同学:schoolmate1,schoolmate2;
  • CommentNames 字段存储用户好友备注列表数据,以用户ID + : + 备注为一个好友的备注信息,多个备注信息之间以;分割。例如:10000:张三;10001:李四
  • HeadImageIndex 字段存储系统默认头像索引数据,当用户上传头像后,HeadImageData 字段会被赋值,且HeadImageIndex 字段值被设置为-1
  • Version 字段保存用户的版本,初始值为0,每当用户的信息更新,本字段值+1。

2. GGGroup(群组表)

所有创建的群都保存在该表中。

字段名称 字段类型 字段说明
GroupID varchar(20) 群组ID,主键
Name varchar(20) 群组名称
CreatorID varchar(20) 群组创建者的用户ID
Announce varchar(200) 群公告
Members varchar(4000) 群组成员的用户ID列表,以 , 分隔
IsPrivate tinyint 是否允许群组成员之间私聊:0不允许,1允许
CreateTime datetime 创建群组的时间节点
Version int 群组版本

补充说明:

  • Version 字段保存群组在版本,初始值为0,每当群组在信息更新,本字段值+1。
  • Members 字段存储群组成员的用户ID列表数据,注意这个字段和 GGUser表 中的Groups 字段间存在联动关系。例如:当一个用户退出一个群时,这个用户的Groups中会少一个群组ID,同时这个群组的Members中会少一个用户ID。

3. OfflineMessage(离线消息记录表)

此表用于存储离线消息数据。

字段名称 字段类型 字段说明
AutoID int 自增ID,主键
SourceUserID varchar(50) 发送离线消息的用户ID
DestUserID varchar(50) 接收离线消息的用户ID
SourceType int 发送者的设备类型:1DotNET,2Android,4IOS,9Linux
GroupID varchar(50) 该字段用于群离线消息
InformationType int 信息的类型
Information longblob 信息内容
Tag varchar(100) 附带信息
TimeTransfer datetime 服务器接收到要转发离线消息的时间

补充说明:

  • 当离线用户上线时,服务器会把这条消息转发给该用户,同时这条消息会从表中删除。
  • TimeTransfer 字段存储离线文件的路径,默认在服务端程序根目录\bin\Debug\OfflineFiles\接受者的用户ID作为文件名目录下。

4. OfflineFileItem(离线文件表)

当目标用户不在线时,发送给他的文件对应的记录存在该表中。

字段名称 字段类型 字段说明
AutoID int 自增ID,主键
FileName varchar(100) 文件名
FileLength int 文件长度
SenderID varchar(50) 发送者的用户ID
SenderType int 发送者的设备类型:1DotNET,2Android,4IOS,9Linux
AccepterType int 接受者的设备类型:1DotNET,2Android,4IOS,9Linux
AccepterID varchar(50) 接收者的用户ID
RelayFilePath varchar(300) 转发文件的路径

补充说明:
离线文件默认存在服务端的运行目录下的OfflineFiles文件夹下,RelayFilePath 指明了具体的相对路径。
当离线用户上线时,服务器会把这个文件转发给该用户,同时这个文件会从表中删除。

5. GroupBan(群禁言表)

当群中的用户被禁言时,对应的记录将存在该表中。

字段名称 字段类型 字段说明
AutoID int 自增ID,主键
GroupID varchar(20) 群组ID
OperatorID varchar(20) 禁言者的用户ID
UserID varchar(20) 被禁言者的用户ID
Comment2 varchar(50) 本次禁言的备注
EnableTime datetime 本次禁言的截至时间
CreateTime datetime 本次禁言的开始时间

6. ChatMessageRecord(聊天消息记录表)

此表用于存储聊天消息数据。

字段名称 字段类型 字段说明
AutoID bigint 自增ID,主键
SpeakerID varchar(20) 发言者的用户ID
AudienceID varchar(20) 倾听者的用户ID或群组ID
IsGroupChat bit(1) 是否是群组聊天:0不是,1是
Content longblob 聊天内容
OccureTime datetime 消息发送的时间节点

补充说明:
该表除了主键之外,还建有两个联合索引:
KEY IX_ChatMessageRecord (SpeakerID,AudienceID,OccureTime) USING BTREE
KEY IX_ChatMessageRecord_1 (AudienceID,OccureTime) USING BTREE
这两个联合索引,与客户端两种查询聊天记录的方式一一对应。
如此,服务端可以快速地从数据库中加载满足条件的聊天记录返回给客户端。

7. AddFriendRequest(加好友请求表)

所有添加好友的请求消息都存在该表中。

字段名称 字段类型 字段说明
AutoID int 自增ID,主键
RequesterID varchar(50) 申请者的用户ID
AccepterID varchar(50) 接收者的用户ID
RequesterCatalogName varchar(20) 申请者的分组名称
AccepterCatalogName varchar(20) 接受者的分组名称
Comment2 varchar(500) 申请时的备注信息
State int 本次申请的状态:0请求中,1同意,2拒绝
Notified bit(1) 申请是否通知对方:0不通知,1通知
CreateTime datetime 申请添加好友的时间节点

8. AddGroupRequest(入群请求表)

所有申请入群的请求消息都存在该表中。

字段名称 字段类型 字段说明
AutoID int 自增ID,主键
RequesterID varchar(20) 申请者的用户ID
GroupID varchar(20) 群组ID
AccepterID varchar(20) 接收者的用户ID
Comment2 varchar(500) 申请时的备注信息
State int 本次申请的状态:0请求中,1同意,2拒绝
Notified bit(1) 申请是否通知对方:0不通知,1通知
CreateTime datetime 申请加入群组的时间节点

9. GGConfiguration(系统配置表)

用于预留存储与GGTalk相关的配置信息。

字段名称 字段类型 字段说明
GGKey varchar(20) 配置的键名
GGValue varchar(1000) 配置的键值

三. 小结

GGTalk 的数据库只有9张表,而且都比较简单。
每个表都有唯一的主键。
就实际使用来看,ChatMessageRecord 聊天记录表的数据量将是最大的,所以,ChatMessageRecord 表必须建联合索引,以支持快速查询。
在我们接到的定制项目中,对于那些同时在线用户量较大的(比如同时在线大于1万人)使用场景,ChatMessageRecord 我们会采取按月分表的策略来应对,在这种情况下,GGTalk 的服务端代码需要做相应的调整。有机会用到这种策略的朋友,可以和我们交流更多关于该策略的实现方案。
作为《GGTalk源码剖析》的第一篇,差不多就这样了。在接下来的一篇我们将介绍GGTalk服务端全局缓存。
敬请期待:《GGTalk 开源即时通讯系统源码剖析之:服务端全局缓存

posted @ 2023-07-04 11:01  C#开源即时通讯GGTalk  阅读(1195)  评论(3编辑  收藏  举报