上一篇文章概括地描述了千尋使用的通訊方式和數據庫,本篇文章我們將重點探討一下千尋的數據庫該如何設計。
在設計數據庫前,我將千尋涉及到的主要功能列在下面。當然實際上,在明確功能點和需求上,更好的手段是編寫用戶故事。不過,這裏還是用這樣簡單的方式來說明問題:
- 註冊、登錄,個人資料包括性別、出生日期、簽名、照片、星座、學校等
- 通過通訊錄、郵箱等方式添加好友
- 點對點聊天
- 發現周圍人
- 利用興趣愛好來輔助查找周圍人
- 好友分組
- 設置在線狀態:在線、僅好友可見、隱身
- 創建基於話題和基於好友的兩種討論組
- 發起活動,活動包括標題、地點(可選)、簡介等信息
- 參與活動
- 白板討論
結合上篇文章所述關於數據持久化的內容,我們對這些功能涉及到的數據做如下區分:
- 保存在MongoDB中、緩存在Redis中的數據
- 保存在Redis中的數據
第一類數據包括:
-
用戶信息(UserProfile)
用戶信息包括用戶名(郵箱)、密碼(MD5+salt)、暱稱、性別、出生日期、星座、簽名、學校、職業、手機號、上次活動時間和地理位置等基本信息。此外用戶信息文檔(Document)裏,還保存有好友集合、好友分組集合、標籤(如興趣)集合。這些信息可以以列表的形式保存在MongoDB中。
此外,還需要對郵箱、手機號和地理位置建立索引,以便快速查找。
-
活動信息(Activity)
活動信息包括活動的標題、活動時間、活動地點(文字描述+座標)、簡介、發起人和參與者列表。
爲了進一步提高效率,我們還需要使用Redis作爲緩存來保存這些數據及相關結果:
-
當用戶上線時,用戶的信息應當被加載到Redis中,存儲方式爲:
-
在線列表
無序集合。key: "onlines", val: ("user_id1", "user_id2", ...)
-
用戶資料
信息:哈希。key: "user:user_id", val: {"username": XXX, "gender": XXX, ...}
好友&分組:無序集合。key: "groups:user_id:group_name",val: ("user_id1", "user_id2", ...)
興趣:無序集合。key: "interests:user_id", val: ("word1", "word2", ...)
-
-
系統啓動時,活躍用戶(例如最近7天有過活動的用戶)的資料也按上述方式加載到Redis中。
-
系統啓動時,從過去某一天(例如30天前)起的活動被加載到內存中:
基本信息:哈希。key: "activity:activity_id", val: {"title": XXX, "introduction":XXX, "place": XXX, "position": XXX, ...}
活動參與者:無序集合。key: "activity:activity_id:participants", val: ("user_id1", "user_id2", ...)
發起的活動:有序列表(按照活動日期排列)。key: "activity:user_id:own", val: ("activity_id1", "activity_id2", ...)
參與的活動:有序列表(按照活動日期排列)。key: "activity:user_id:in", val: ("activity_id1", "activity_id2", ...)
第二類數據包括:
-
點對點消息
有序列表。key: "message:from_id:to_id",val: ["time|content", "time|content", ...]
-
話題討論組
有序列表。key: "topic:sub_id:topic_name", val: ["nickname|time|content", "nickname|time|content", ...]
-
好友討論組
討論組列表:無序集合。key: "chatgrp:user_id:list:group_name",val: ("user_id1", "user_id2", ...)
討論組消息:有序列表。key: "chatgrp:sub_id:msg:group_name", val:["nickname|time|content", "nickname|time|content", ...]
-
白板討論
使用"Pub/Sub"功能即可。