GGTalk 開源即時通訊系統原始碼剖析之:資料庫設計

2023-07-04 12:00:29

自從《開源即時通訊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 開源即時通訊系統原始碼剖析之:伺服器端全域性快取》