自從《開源即時通訊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 資料庫一共涉及到九張表,分別為:
下面將分別對每一張表的欄位進行說明。
所有註冊使用者都儲存在該表中。
欄位名稱 | 欄位型別 | 欄位說明 |
---|---|---|
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。所有建立的群都儲存在該表中。
欄位名稱 | 欄位型別 | 欄位說明 |
---|---|---|
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。此表用於儲存離線訊息資料。
欄位名稱 | 欄位型別 | 欄位說明 |
---|---|---|
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作為檔名
目錄下。當目標使用者不線上時,傳送給他的檔案對應的記錄存在該表中。
欄位名稱 | 欄位型別 | 欄位說明 |
---|---|---|
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 指明瞭具體的相對路徑。
當離線使用者上線時,伺服器會把這個檔案轉發給該使用者,同時這個檔案會從表中刪除。
當群中的使用者被禁言時,對應的記錄將存在該表中。
欄位名稱 | 欄位型別 | 欄位說明 |
---|---|---|
AutoID | int |
自增ID,主鍵 |
GroupID | varchar(20) |
群組ID |
OperatorID | varchar(20) |
禁言者的使用者ID |
UserID | varchar(20) |
被禁言者的使用者ID |
Comment2 | varchar(50) |
本次禁言的備註 |
EnableTime | datetime |
本次禁言的截至時間 |
CreateTime | datetime |
本次禁言的開始時間 |
此表用於儲存聊天訊息資料。
欄位名稱 | 欄位型別 | 欄位說明 |
---|---|---|
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
這兩個聯合索引,與使用者端兩種查詢聊天記錄的方式一一對應。
如此,伺服器端可以快速地從資料庫中載入滿足條件的聊天記錄返回給使用者端。
所有新增好友的請求訊息都存在該表中。
欄位名稱 | 欄位型別 | 欄位說明 |
---|---|---|
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 |
申請新增好友的時間節點 |
所有申請入群的請求訊息都存在該表中。
欄位名稱 | 欄位型別 | 欄位說明 |
---|---|---|
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 |
申請加入群組的時間節點 |
用於預留儲存與GGTalk相關的設定資訊。
欄位名稱 | 欄位型別 | 欄位說明 |
---|---|---|
GGKey | varchar(20) |
設定的鍵名 |
GGValue | varchar(1000) |
設定的鍵值 |
GGTalk 的資料庫只有9張表,而且都比較簡單。
每個表都有唯一的主鍵。
就實際使用來看,ChatMessageRecord 聊天記錄表的資料量將是最大的,所以,ChatMessageRecord 表必須建聯合索引,以支援快速查詢。
在我們接到的客製化專案中,對於那些同時線上使用者量較大的(比如同時線上大於1萬人)使用場景,ChatMessageRecord 我們會採取按月分表的策略來應對,在這種情況下,GGTalk 的伺服器端程式碼需要做相應的調整。有機會用到這種策略的朋友,可以和我們交流更多關於該策略的實現方案。
作為《GGTalk原始碼剖析》的第一篇,差不多就這樣了。在接下來的一篇我們將介紹GGTalk伺服器端全域性快取。
敬請期待:《GGTalk 開源即時通訊系統原始碼剖析之:伺服器端全域性快取》