马关条约后的李鸿章:MongoDB的应用:动态消息的设计实现

来源:百度文库 编辑:九乡新闻网 时间:2024/04/28 12:50:54

MongoDB的应用:动态消息的设计实现

标签: MongoDB 动态设计 oecp社区 nosql现在社交网站异常火爆,Facebook、人人、开心网在短短的几年内,引领了互联网的又一个时代—网络社交,如果说,第一个时代是通过门户网站提供的内容,第二个时代是通过搜索引擎来主动获取内容,那么作为第三个时代的SNS,又是通过什么来进行的信息的传播呢?当然是利用的人与人之间的关系形成的网,进行人与人之间的传播,而实现这种病毒式传播的工具就是信息的动态推送。
在OECP社区的策划设计时,我们不仅仅要做高质量的内容站点,另外很重要的部分就是要把这些高质量的内容主动的推送给用户,而要达到这种目标的手段就是要有动态信息的推送功能。在一般的SNS系统中,朋友是维系人与人之间关系的纽带,而OECP社区中,维系人与人之间的纽带是什么,是共同关注的内容。所以我们设计了关注功能来加强人与人之间关系和内容的直接推送。
OECP社区是一个以业务组件为主题的社区,所以OECP社区的关注对象除了用户外,还要有业务组件。下图为关注的关系图。

建立好关注的关系以后,我们就要根据用户建立的这些关系为用户推送相关动态。
 
如何设计消息动态功能呢?我们先来分析几个问题:
  • 社区的动作比较频繁,产生的动态数据是实时存储,还是缓存后延迟存储,对效率有什么影响。
  • 每个人产生的动态消息要在被关注的人之间分发,数据的膨胀速度非常快,如何解决大数据量的存储问题?
  • 数据量非常庞大的时候,如何能提高我们读取的效率,普通的做法是采用缓存功能,是不是有其他的方法,能够保证程序即方便开发,又高效呢?
 
参考: SNS中好友动态功能的设计思路
 
综合考虑以上因素,我们放弃了利用关系数据库的方案,而采用现在比较流行的MongoDB来存储。主要原因:
  • 采用缓存机制进行存储和读取处理,增加开发的难度。
  • MongoDB是一个解决海量存储的文档型数据库,无模式的结构可以让存储的数据结构更加灵活。在普通的关系数据库中,不同类型的消息的内容要存在一个字段中,一般采用JSON的格式存储,然后根据不同类型在解析显示出来。而MongoDB的无模式结构,就可以自由的定义各种字段,一个表中都可以存储不同字段定义的数据,前台可以直接引用,非常方便。
  • 在大数据量下的查询中,MongoDB的查询性能还是非常好的,所以MongoDB都可以作为基础缓存层。更为重要的是,MongoDB的写性能要远远强过非关系数据库。通过这个特性,我们就无需在设立缓存层,而直接实时的插入和查询,方便的开发。
 
MongoDB有一个ORM的实现,项目地址:http://code.google.com/p/morphia/
 
但是鉴于存储的同一个表中的数据结构不一致,我们就是要利用MongoDB的无模式的存储方式,故放弃了这种POJO的实现。接下来我们要开始设计MongDB的存储结构了。下面是UML类图:
 
首先要定义一个存储动态的结构:Dynamic
Channel-->动态所在的频道,比如博客、业务组件等,参见枚举类DynamicChannel
Type-->动态的类型,比如博客、关注、留言等,参见枚举类DynamicType
UserId-->产生该动态消息的用户编号
TargetId-->动态事件所关联的实体编号,比如发表了一篇博客,该处为博客ID
CreateTime-->动态产生的时间
BcIdà业务组件编号,如果该动态和业务组件有关系,则记录该业务组件的编号,以方便根据此显示业务组件的最新动态。
Data-->动态消息的内容。如果用关系型数据库存储的话,一般存储JSON结构的数据。该处我们直接定义了一个结构类,参见DynamicData
 
动态消息的结构设计完成以后,我们需要把这些消息推送到不同用户那里,所以必须定义一个用户动态类UserDynamic
Uid-->用户名
DynamicId-->Dynamic的ID
Channel-->动态所在的频道,比如博客、业务组件等,参见枚举类DynamicChannel
CreateTime-->动态产生的时间
BcId-->组件ID
 
为了能够在用户的个人空间里按照频道来查询用户的动态,我们需要存储Channel,为了能够方便检索用户关注的哪个组件的动态,我们存储了BcId。如果我们还要更加细分到检索我关注的某个用户的动态,我们还需要在UserDynamic增加EventUserId。也许我们要问,为什么要加这么多的冗余,因为这些字段在Dynamic都已经存在了。这就是因为MongoDB不是关系型的数据库,无法通过类似于关系数据库的关联查询进行读取,表和表之间也是独立的,其实它没有表的概念,它的定义是Collection,所以我们必须在一个Collection中定义好我们需要的字段属性。
 
接下来我们就要设计功能的实现方式和解决方案。
  • 采用事件机制(观察者模式),为各种业务操作定义不同的事件。该部分的设计思路OECP社区的其他同事随后会更大家分享。
  • 编写动态监听器,对我关注的一些事件进行监听,并将监听到的内容传递给动态服务。
  • 编写统一的动态处理服务,采用异步的方式,对动态进行实时的分发。
  • 编写MongoDB统一的DAO
 
以后将陆续发布基于MongoDB的架构和设计实现的相关文章,敬请关注!

下面截取了几个图来展示动态在OECP社区中的效果:
全站动态:

用户的动态:

我的动态:

关注:
 


1、
/**
 *动态所属的频道
 *
 *@authoryongtree
 *@date2010-8-13上午11:23:39
 *@version1.0
 */
public enum DynamicChannel {
 
    @EnumDescription("博客")
    Blog, @EnumDescription("业务组件")
    BC, @EnumDescription("关注")
    Attention,
    @EnumDescription("留言")
    LeaveWord,
    @EnumDescription("其他")
    Other
 
}
2、
/**
 *动态类型

 *注释描述了相关的存储数据结构
 *
 *@authoryongtree
 *@date2010-8-12下午06:37:12
 *@version1.0
 */
public enum DynamicType {
 
    @EnumDescription("发表博客")
    Blog, // {title:'博客标题',summary:'博客描述'}
    @EnumDescription("回复博客")
    PostBlog, // {title:'博客标题',summary:'评论的内容','uid','博主uid'}
    @EnumDescription("留言")
    LeaveWord, // {touid:'yt',touname:'谭明智',summary:'留言内容'}
    @EnumDescription("新开通业务组件")
    NewBC, // {bcname:'组件的名称',bccode:'bc1'}
    @EnumDescription("创建组件主题")
    BCSubject, // {title:'主题的名称',subjectId:'subject',bccode:'bc1',bcvc:'1.0',bcname:'财务总帐组件'}
    @EnumDescription("发布组件WIKI")
    BCWiki, // {title:'文章标题',bccode:'bc1',bcvc:'1.0',bcname:'财务总帐组件'}
    @EnumDescription("挑错")
    BCMistake, // {title:'文章标题',summary:'评论的内容',bccode:'bc1',bcvc:'1.0',bcname:'财务总帐组件'}
    @EnumDescription("评论组件WIKI")
    PostBCWiki, // {title:'文章标题',summary:'评论的内容',bccode:'bc1',bcvc:'1.0',bcname:'财务总帐组件',isSection:true[如果是true的话,则title是section的标题,否则为subject的标题],subjectId:'entity'}
    @EnumDescription("发起组件讨论")
    BCTopic, // {title:'讨论的主题',bccode:'bc1',bcname:'财务总帐组件'}
    @EnumDescription("回复组件讨论")
    BCPost, // {title:'讨论的主题',bccode:'bc1',bcname:'财务总帐组件'}
    @EnumDescription("加入组件")
    BCJoin, // {bcname:'财务总帐组件',bccode:'bc1'}
    @EnumDescription("关注用户")
    AttendUser, // {uid:'yt',username:'谭明智'}
    @EnumDescription("关注组件")
    AttendBC, // {bcname:'财务总帐组件',bccode:'bc1'}
    @EnumDescription("加入本站")
    Reg
    // {}
 
}
 相关文件请参考附件。

附件:

基于MongoDB的动态消息的设计实现.pdfMongoService.javaMongoFSServiceImpl.javaMongoFSService.javaMongoFSServiceImpl.java
    旧一篇:给敏捷团队中的架构师的10个建议  |  新一篇:谈谈设计不足与过度设计