最近关注了下SNS好友动态的功能,发现这个功能的技术点其实与微博使用技术很是相似.
不同点就是两者的数据量不同,SNS好友一般都有数量限制,而且在SNS的理论里,个人好友的合理数量在150个左右(最近有文章说Facebook的人均好友数是120人 ).
最简单的数据表结构就是类似日志样的
ID //消息ID
UserID //用户ID
MsgType //消息类型,比如加好友、上传照片等不同的类型
EventMsg //消息的内容,这里我们可以用Json的数据格式来描述出不同的活动内容
CreateTime //消息创建时间
这是最简单的方法了,简单也就带来了问题
这个结构也是个数据库的结构,当用户做个一个动作之后,就会创建这样一个消息,并保存在数据库中,当显示好友的活动信息时,就从这张表里查询自己好友id 的数据,并按时间显示,这个做法是一个最简单的实现,但会出现一些问题,当你与一个用户成为好友之后,该好友之前发生的动作会显示出来,而不是在成为好友 时点之后的动作,同样,切断好友关系之后也有类似的问题,如果从业务角度和用户体验上可以接受的话,也没什么,但由于信息是按时间排序,有时候会给用户错 乱的感觉,还有,这个信息不能删除,如果删除了所有好友就看不到这条信息了,但在Facebook里是则是可以删除好友的动作信息的,这个方法还有一个问 题是,所有信息都放在一张大表里,在信息爆炸增长,个人好友也很多的情况下,查询效率会非常低,产生严重的性能障碍,如果对这张表做水平切分,则在实现上 复杂了许多,性能也未必好很多,接下来我们再思考是否有更好的解决办法。
对于以上两点问题:一是成为好友之前的信息也显示;二是不能删除信息.
可以做以下改进:
一种方法就是
首先看数据库设计,我们要把信息表和信息与用户的对应表分开,我们上面定义的数据结构保留,我们定义它的表名为Event,我们再新建一张表EventUser,结构如下
ID //主键
EventID //Event表的ID
FriendUserID //好友的ID
CreateTime //消息创建时间对FriendUserID做索引,当用户发生动作时,首先将动作信息写入Event表,之后查找用户的所有好友,将EventID、好友ID逐条 写入EventUser表,当要显示自己的好友活动信息是,查询EventUser中FriendUserID等于自己ID的信息,并和Event表做一 个Join查询就可以了。
第二种方法就是复制信息,当出现一条新的动态之后,把在数据库中复制好友数量的动态.
这个方法也是新浪微博的第一个版本架构.
这种方法相当简单,单库单表,将发表/订阅变成了简单的insert/select.
当数据量很大的时候,这个架构是不能胜任的,会出现数据延迟,锁表等问题.
必须对推模式进行改进.
同步:http://www.java1995.cn/blog/item/482