千寻的架构设计(二)

发布于2012年3月10日 -

上一篇文章概括地描述了千寻使用的通讯方式和数据库,本篇文章我们将重点探讨一下千寻的数据库该如何设计。

在设计数据库前,我将千寻涉及到的主要功能列在下面。当然实际上,在明确功能点和需求上,更好的手段是编写用户故事。不过,这里还是用这样简单的方式来说明问题:

  • 注册、登录,个人资料包括性别、出生日期、签名、照片、星座、学校等
  • 通过通讯录、邮箱等方式添加好友
  • 点对点聊天
  • 发现周围人
  • 利用兴趣爱好来辅助查找周围人
  • 好友分组
  • 设置在线状态:在线、仅好友可见、隐身
  • 创建基于话题和基于好友的两种讨论组
  • 发起活动,活动包括标题、地点(可选)、简介等信息
  • 参与活动
  • 白板讨论

结合上篇文章所述关于数据持久化的内容,我们对这些功能涉及到的数据做如下区分:

  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"功能即可。