千尋的架構設計(二)

Posted on March 10, 2012 -

上一篇文章概括地描述了千尋使用的通訊方式和數據庫,本篇文章我們將重點探討一下千尋的數據庫該如何設計。

在設計數據庫前,我將千尋涉及到的主要功能列在下面。當然實際上,在明確功能點和需求上,更好的手段是編寫用戶故事。不過,這裏還是用這樣簡單的方式來說明問題:

  • 註冊、登錄,個人資料包括性別、出生日期、簽名、照片、星座、學校等
  • 通過通訊錄、郵箱等方式添加好友
  • 點對點聊天
  • 發現周圍人
  • 利用興趣愛好來輔助查找周圍人
  • 好友分組
  • 設置在線狀態:在線、僅好友可見、隱身
  • 創建基於話題和基於好友的兩種討論組
  • 發起活動,活動包括標題、地點(可選)、簡介等信息
  • 參與活動
  • 白板討論

結合上篇文章所述關於數據持久化的內容,我們對這些功能涉及到的數據做如下區分:

  1. 保存在MongoDB中、緩存在Redis中的數據
  2. 保存在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"功能即可。