做SNS的,一起来猜猜新浪微博的核心Feed系统是怎么设计的吧
要是不清楚什么是feed,google之。
Feed是sns类应用的核心和最复杂的部分,就是sina微博中看到的“我关注的人”的消息。像人人网中的“新鲜事”等等,都是一个东西。你想啊,你关注了几千人,又被几千人关注,你发了一个消息,另外几千人怎么看到哪?拿数据库做join和in操作肯定立刻挂。而且像sina weibo,数据和访问量庞大,怎么实现哪?这其实就是传说中的推和拉的选择,人人网写过一篇文章:http://news.csdn.net/a/20100726/277273.html,简单来说以推为主体。我猜测可能在某些情况下会使用拉,例如这个账号很久不登录,太不活跃,给他推东西纯属浪费。嗯。。。,这方面也欢迎一起来猜猜。
基于这些,我猜测的第1版架构图(我们现在就是这样做的,规模比较小,还看不出问题):
整个架构基于memcached + mysql,图中分了ABC三个区域。所有的消息存储在mysql中,无论推送给多少人,只存储一份。另外有一个索引表,用来记录推送关系,推送给1000个人,就增加1000条记录,也就是图中的A。当发生查询时,从索引表中根据用户编号进行一次简单查询(基于用户编号为索引和条件的select),拿到索引结果后,进入B,从memcached中读取实际信息。如果不存在或者不全,进入C,根据索引信息读取网友实际发表或者转载的内容,用模板生成消息并存储到memcached中,然后返回来。
在整个过程中,B是memcached集群,性能应该问题不大。C是cache后面的东西,其中的数据库查询也是基于索引表中给的对象主键,分表条件等进行的分库分表基于主键的查询,性能问题应该也不大。关键是A区。我们现在的方案是用guzz框架把索引表分到单独的一组数据库中,然后根据用户id进行切表,每个人保留最多200条最新消息的索引。总的来说,每张表的大小还在控制内。对于像#话题#等也是一样的,建立索引表分发。无论怎样,实际的消息只有一份。
我猜测,sina微博第一版系统应该就是这样。架构简单实用。
但随着规模的扩大,A区索引表肯定会逐步出现大量性能问题。要升级到第二,第三版。这两个之间或许是一步到位的。
第二第三版架构猜测:
A区的性能问题不是mysql能够解决的,但幸好A区的数据结构非常简单。就是以 用户id+某个动态功能 为key下的一个固定大小的索引集合。最简单的办法就是把mysql换成nosql,这个数据结构用nosql应该非常容易实施。我没有用过nosql,但通过资料来看,相比mysql肯定是一大性能提升。我们暂且推测其为第二版方案吧。欢迎实际用过nosql的来谈谈行不行。
我们假设,第二版方案也解决不了问题。A区的性能问题太大了,怎么办?如果这样,我想索引系统只能是自己做了,谁也靠不住。我有个猜测,欢迎讨论。看下图。
这个架构是完全为feed定制的,我们为每个 用户id+某个动态功能 分配一个磁盘block。在索引表中,我们知道每条索引记录的大小是固定的(假设每条1k大小),而为用户提供的最多最新动态数也是固定的(假设200条)。那么我们这个block就分配固定的201K,前面的1k是头信息,后面的200k存储最多200条的索引记录。
在头信息中,记录这个块操作的系统版本号(升级使用),用户信息,操作的偏移量,总动态数等等。当插入一条新索引时,根据操作偏移量直接定位位置,写入;如果已经写到第200条,回到第一条覆盖写。读取的时候,根据偏移量数据直接读。因为记录大小固定,block维护简单,顺序读写,效率肯定不差。而这些block文件块,将存储在一套分布式文件系统中,依靠还算成熟的hadoop技术,无限扩展这个大集群。
相比数据库的优势,还省去了清理过期数据的问题。
这里面没有讨论block块缓存的问题,这是分布式文件系统的工作。对于不同的动态,可能block的大小会不一样,这都是可以的。
不知道猜的对不对。
37 楼 myreligion 2011-03-10 抛出异常的爱 写道ray_linn 写道说句不客气的,微博就是垃圾堆,而数据库不是存垃圾的地方,所以是垃圾的东西就不需要用数据库,只需要回到本来面目---文本格式就可以。
用户----我关注的用户,是个一对多的关系。这种connection不是垃圾,可以放数据库里。
每个用户有自己独立的folder(以ID code为名),自己发表的垃圾,就堆在这个folder里,当场就生成静态html。
然后一个用户登录了,就到自己关注的用户的folder里东读一点西读一点,其实都是静态HTML,你要觉得硬盘IO太多,也不妨放个memcache,不放,也不见得会怎么样。
至于这些文本怎么删除,其实只要跟踪一下用户登录就可以,还登录的用户是hot user,他们的内容可以keep住,不是hot user的,folder就可以由后台清空了
如果有新的微博是否需要f5来刷新?
如果非f5刷新那怎么通知到?
靠对所有跟随者广播么?
如果广播那怎么知道我的跟随者是否在线?(非在线不通知)
如果收到了广播通知如何通知浏览器F5刷新页面?
如果刷新页面时是把所有新消息都刷出来还是只刷出来刚刚广播的消息?
以上求解惑
@ray_linn说的很有道理,垃圾信息回归垃圾模式处理就行了,呵呵。
对于刷新,我觉得应该是ajax模式。对于主贴上第三版设计,页面打开时会同时在js中记录下偏移量,然后定期的或者像gmail那样保持长连接的去查询。当服务器发现偏移量变化时,根据偏移量得到新的索引数据,把新的消息发送给客户端,然后更新客户端中偏移量的值到最新值。
对于分布式文件系统模式,吞吐量肯定是非常庞大的,不会有网络400M之类的流量限制,很多设计可以简单很多。
上面提到的客户端可以是浏览器,也可以是手机客户端之类的。应该都可以。
我猜是这样~~
38 楼 ldd600 2011-03-10 采用推的形式,分布式队列,异步化。
行级缓存:memcached,redis。存消息主体。
列级缓存:redis,TT,存收件箱和订阅关系。
注意处理关系列表时,大数据量的问题。
Mysql:用户分表,存订阅关系。动态,按时间分表。 39 楼 抛出异常的爱 2011-03-10 myreligion 写道抛出异常的爱 写道ray_linn 写道说句不客气的,微博就是垃圾堆,而数据库不是存垃圾的地方,所以是垃圾的东西就不需要用数据库,只需要回到本来面目---文本格式就可以。
用户----我关注的用户,是个一对多的关系。这种connection不是垃圾,可以放数据库里。
每个用户有自己独立的folder(以ID code为名),自己发表的垃圾,就堆在这个folder里,当场就生成静态html。
然后一个用户登录了,就到自己关注的用户的folder里东读一点西读一点,其实都是静态HTML,你要觉得硬盘IO太多,也不妨放个memcache,不放,也不见得会怎么样。
至于这些文本怎么删除,其实只要跟踪一下用户登录就可以,还登录的用户是hot user,他们的内容可以keep住,不是hot user的,folder就可以由后台清空了
如果有新的微博是否需要f5来刷新?
如果非f5刷新那怎么通知到?
靠对所有跟随者广播么?
如果广播那怎么知道我的跟随者是否在线?(非在线不通知)
如果收到了广播通知如何通知浏览器F5刷新页面?
如果刷新页面时是把所有新消息都刷出来还是只刷出来刚刚广播的消息?
以上求解惑
@ray_linn说的很有道理,垃圾信息回归垃圾模式处理就行了,呵呵。
对于刷新,我觉得应该是ajax模式。对于主贴上第三版设计,页面打开时会同时在js中记录下偏移量,然后定期的或者像gmail那样保持长连接的去查询。当服务器发现偏移量变化时,根据偏移量得到新的索引数据,把新的消息发送给客户端,然后更新客户端中偏移量的值到最新值。
对于分布式文件系统模式,吞吐量肯定是非常庞大的,不会有网络400M之类的流量限制,很多设计可以简单很多。
上面提到的客户端可以是浏览器,也可以是手机客户端之类的。应该都可以。
我猜是这样~~
ajax memcache等高深词汇对于
几百人同时在线可以完成的不错.....
400M流量....有时还要再想想.....
你说过的长连接很有意思
能细说说怎么用么 40 楼 myreligion 2011-03-10 抛出异常的爱 写道myreligion 写道抛出异常的爱 写道ray_linn 写道说句不客气的,微博就是垃圾堆,而数据库不是存垃圾的地方,所以是垃圾的东西就不需要用数据库,只需要回到本来面目---文本格式就可以。
用户----我关注的用户,是个一对多的关系。这种connection不是垃圾,可以放数据库里。
每个用户有自己独立的folder(以ID code为名),自己发表的垃圾,就堆在这个folder里,当场就生成静态html。
然后一个用户登录了,就到自己关注的用户的folder里东读一点西读一点,其实都是静态HTML,你要觉得硬盘IO太多,也不妨放个memcache,不放,也不见得会怎么样。
至于这些文本怎么删除,其实只要跟踪一下用户登录就可以,还登录的用户是hot user,他们的内容可以keep住,不是hot user的,folder就可以由后台清空了
如果有新的微博是否需要f5来刷新?
如果非f5刷新那怎么通知到?
靠对所有跟随者广播么?
如果广播那怎么知道我的跟随者是否在线?(非在线不通知)
如果收到了广播通知如何通知浏览器F5刷新页面?
如果刷新页面时是把所有新消息都刷出来还是只刷出来刚刚广播的消息?
以上求解惑
@ray_linn说的很有道理,垃圾信息回归垃圾模式处理就行了,呵呵。
对于刷新,我觉得应该是ajax模式。对于主贴上第三版设计,页面打开时会同时在js中记录下偏移量,然后定期的或者像gmail那样保持长连接的去查询。当服务器发现偏移量变化时,根据偏移量得到新的索引数据,把新的消息发送给客户端,然后更新客户端中偏移量的值到最新值。
对于分布式文件系统模式,吞吐量肯定是非常庞大的,不会有网络400M之类的流量限制,很多设计可以简单很多。
上面提到的客户端可以是浏览器,也可以是手机客户端之类的。应该都可以。
我猜是这样~~
ajax memcache等高深词汇对于
几百人同时在线可以完成的不错.....
400M流量....有时还要再想想.....
你说过的长连接很有意思
能细说说怎么用么
长连接好像有个名词是comet
41 楼 ray_linn 2011-03-10 myreligion 写道
长连接好像有个名词是comet
comet不是万能狗皮膏药。众所周知,http之所以设计成短连接,就是为了能够服务尽量多的客户。(下一个网页你都要看半天)。
轮询的方式也未必就差到哪里去,polling 还是 comet 还是piggypolling,这只是个小策略问题。
单从 io的效率来看,文本文件效率永远高于NOSQL和SQL 42 楼 抛出异常的爱 2011-03-10 ray_linn 写道myreligion 写道
长连接好像有个名词是comet
comet不是万能狗皮膏药。众所周知,http之所以设计成短连接,就是为了能够服务尽量多的客户。(下一个网页你都要看半天)。
轮询的方式也未必就差到哪里去,polling 还是 comet 还是piggypolling,这只是个小策略问题。
单从 io的效率来看,文本文件效率永远高于NOSQL和SQL
我一直以为是由于以前的io没有nio那么多连接可用.....
减少请求再减少请求
可能是这种密集web2.0的技术难点
分析统计等功能会渐渐分散到个人并由人肉智能代替. 43 楼 ldd600 2011-03-10 抛出异常的爱 写道ray_linn 写道myreligion 写道
长连接好像有个名词是comet
comet不是万能狗皮膏药。众所周知,http之所以设计成短连接,就是为了能够服务尽量多的客户。(下一个网页你都要看半天)。
轮询的方式也未必就差到哪里去,polling 还是 comet 还是piggypolling,这只是个小策略问题。
单从 io的效率来看,文本文件效率永远高于NOSQL和SQL
我一直以为是由于以前的io没有nio那么多连接可用.....
减少请求再减少请求
可能是这种密集web2.0的技术难点
分析统计等功能会渐渐分散到个人并由人肉智能代替.
分析统计等功能会渐渐分散到个人并由人肉智能代替。深有体会。 44 楼 fancyboy2050 2011-03-10 额,俺做一个问答网站的时候新鲜事推送方式类似于楼主的方案一。 45 楼 fancyboy2050 2011-03-10 每个消息的制造者创建一个消息实体到数据库,后台有线程程序分析消息制造者的这个动作并将消息实体的主键分发给各个消费者,我们定义给每个消费者展示多少条feed,在这个线程分发的同时我们会同时更新每个用户的两个缓存消息列表,我们给每个用户创建两个缓存消息列表,一个是需要展示的全部消息列表,一个是实时的消息列表【该列表读取后被清空,用户自己刷新时也会清空】
我们以前是这么干的,感觉跟楼主说的方案一类似^_^ 46 楼 whaosoft 2011-03-10 完了 这个贴我没话语权 么搞过。。。 47 楼 vtrtbb 2011-03-11 觉得他们处理方式会比较特殊,以他们的设计风格来看,比较倾向于系统,不会是一般常规的处理方法。
就像Memcachedb也是他们自己搞的,还有LVS当时也是新浪的章博士搞出来的
也许又发明了什么系统呢 48 楼 ray_linn 2011-03-11 vtrtbb 写道觉得他们处理方式会比较特殊,以他们的设计风格来看,比较倾向于系统,不会是一般常规的处理方法。
就像Memcachedb也是他们自己搞的,还有LVS当时也是新浪的章博士搞出来的
也许又发明了什么系统呢
你觉得互联网的微薄和当初的火鸟BBS有什么区别,无非就是垃圾信息更多了些。如果按我的方案,memcached基本都是靠边站的,要增强的反而是http server自身的cache.
真的要设计,我会把每条信息存成XML格式,其文件名对Browser缓存友好,不使用任何Memcached来缓存静态页面,所有页面由XSLT和javascript在客户端生成。
所以在Web server的cache上动点功夫,减少磁盘io 49 楼 pekkle 2011-03-18 myreligion 写道NanguoCoffee 写道http://www.slideshare.net/iso1600/cache-4842490
刚看了一遍,这些东西有什么看的,是个人都知道,从JLive的论坛年代就开始了id cache。关键是怎么落地。我觉得这个ppt并不比我提出的这个分布式文件系统的方案更有参考价值和讨论价值。
这位老兄的口气挺大的,我看新浪这套方案就挺好的。
比如说您也拿出你的建构方案,跟他比比,让我们无地自容一下,期待。 50 楼 myreligion 2011-03-18 pekkle 写道myreligion 写道NanguoCoffee 写道http://www.slideshare.net/iso1600/cache-4842490
刚看了一遍,这些东西有什么看的,是个人都知道,从JLive的论坛年代就开始了id cache。关键是怎么落地。我觉得这个ppt并不比我提出的这个分布式文件系统的方案更有参考价值和讨论价值。
这位老兄的口气挺大的,我看新浪这套方案就挺好的。
比如说您也拿出你的建构方案,跟他比比,让我们无地自容一下,期待。
对呀,所以说我们讨论啊。我没说sina的架构不好,只是说目前公开的资料太少,有进一步社区探讨的价值。
51 楼 hackwst 2011-03-31 <div class="quote_title">askjsp 写道</div>
<div class="quote_div">
<div class="quote_title">ray_linn 写道</div>
<div class="quote_div">说句不客气的,微博就是垃圾堆,而数据库不是存垃圾的地方,所以是垃圾的东西就不需要用数据库,只需要回到本来面目---文本格式就可以。 <br><br>用户----我关注的用户,是个一对多的关系。这种connection不是垃圾,可以放数据库里。 <br><br>每个用户有自己独立的folder(以ID code为名),自己发表的垃圾,就堆在这个folder里,当场就生成静态html。 <br><br>然后一个用户登录了,就到自己关注的用户的folder里东读一点西读一点,其实都是静态HTML,你要觉得硬盘IO太多,也不妨放个memcache,不放,也不见得会怎么样。 <br><br><br>至于这些文本怎么删除,其实只要跟踪一下用户登录就可以,还登录的用户是hot user,他们的内容可以keep住,不是hot user的,folder就可以由后台清空了</div>
<p>?</p>
<p>?我觉得这个朋友说的有些道理</p>
</div>
<p>我觉得真没道理,估计常常在企业开发里玩这些阴险的玩意</p> 52 楼 hackwst 2011-03-31 ray_linn 写道抛出异常的爱 写道ray_linn 写道说句不客气的,微博就是垃圾堆,而数据库不是存垃圾的地方,所以是垃圾的东西就不需要用数据库,只需要回到本来面目---文本格式就可以。
用户----我关注的用户,是个一对多的关系。这种connection不是垃圾,可以放数据库里。
每个用户有自己独立的folder(以ID code为名),自己发表的垃圾,就堆在这个folder里,当场就生成静态html。
然后一个用户登录了,就到自己关注的用户的folder里东读一点西读一点,其实都是静态HTML,你要觉得硬盘IO太多,也不妨放个memcache,不放,也不见得会怎么样。
至于这些文本怎么删除,其实只要跟踪一下用户登录就可以,还登录的用户是hot user,他们的内容可以keep住,不是hot user的,folder就可以由后台清空了
如果有新的微博是否需要f5来刷新?
如果非f5刷新那怎么通知到?
靠对所有跟随者广播么?
如果广播那怎么知道我的跟随者是否在线?(非在线不通知)
如果收到了广播通知如何通知浏览器F5刷新页面?
如果刷新页面时是把所有新消息都刷出来还是只刷出来刚刚广播的消息?
以上求解惑
javascript难道是吃干饭的吗? 要我设计,每个垃圾信息都设计成xml格式,客户端用XSLT聚合起来就可以,还可以享受免费的browser cache
现在都开始要把数据在内存中玩了,你还非得整到硬盘上玩,我觉得javascript再强,也不至于提高硬盘的I/O瓶颈吧,前端呈现使用什么格式,应该不那么重要吧,设计成xml,那开放API的json格式呢? 53 楼 jd2bs 2011-03-31 ldd600 写道采用推的形式,分布式队列,异步化。
行级缓存:memcached,redis。存消息主体。
列级缓存:redis,TT,存收件箱和订阅关系。
注意处理关系列表时,大数据量的问题。
Mysql:用户分表,存订阅关系。动态,按时间分表。
从杨卫华的微薄看 这位仁兄的说法比较靠谱 54 楼 ldd600 2011-04-06 jd2bs 写道ldd600 写道采用推的形式,分布式队列,异步化。
行级缓存:memcached,redis。存消息主体。
列级缓存:redis,TT,存收件箱和订阅关系。
注意处理关系列表时,大数据量的问题。
Mysql:用户分表,存订阅关系。动态,按时间分表。
从杨卫华的微薄看 这位仁兄的说法比较靠谱
哈哈,排序,排重,删除等都需要好好想想哦。 55 楼 javaeyes 2011-04-12 myreligion 写道抛出异常的爱 写道myreligion 写道抛出异常的爱 写道ray_linn 写道说句不客气的,微博就是垃圾堆,而数据库不是存垃圾的地方,所以是垃圾的东西就不需要用数据库,只需要回到本来面目---文本格式就可以。
用户----我关注的用户,是个一对多的关系。这种connection不是垃圾,可以放数据库里。
每个用户有自己独立的folder(以ID code为名),自己发表的垃圾,就堆在这个folder里,当场就生成静态html。
然后一个用户登录了,就到自己关注的用户的folder里东读一点西读一点,其实都是静态HTML,你要觉得硬盘IO太多,也不妨放个memcache,不放,也不见得会怎么样。
至于这些文本怎么删除,其实只要跟踪一下用户登录就可以,还登录的用户是hot user,他们的内容可以keep住,不是hot user的,folder就可以由后台清空了
如果有新的微博是否需要f5来刷新?
如果非f5刷新那怎么通知到?
靠对所有跟随者广播么?
如果广播那怎么知道我的跟随者是否在线?(非在线不通知)
如果收到了广播通知如何通知浏览器F5刷新页面?
如果刷新页面时是把所有新消息都刷出来还是只刷出来刚刚广播的消息?
以上求解惑
@ray_linn说的很有道理,垃圾信息回归垃圾模式处理就行了,呵呵。
对于刷新,我觉得应该是ajax模式。对于主贴上第三版设计,页面打开时会同时在js中记录下偏移量,然后定期的或者像gmail那样保持长连接的去查询。当服务器发现偏移量变化时,根据偏移量得到新的索引数据,把新的消息发送给客户端,然后更新客户端中偏移量的值到最新值。
对于分布式文件系统模式,吞吐量肯定是非常庞大的,不会有网络400M之类的流量限制,很多设计可以简单很多。
上面提到的客户端可以是浏览器,也可以是手机客户端之类的。应该都可以。
我猜是这样~~
ajax memcache等高深词汇对于
几百人同时在线可以完成的不错.....
400M流量....有时还要再想想.....
你说过的长连接很有意思
能细说说怎么用么
长连接好像有个名词是comet
ray_linn 同学真的太搞笑了,竟然一个用户一个folder,估计做的东西都是内部系统,几十个人用的
56 楼 Rager 2011-04-14 congdepeng 写道java_xiaoyi 写道ch_space 写道peterwei 写道哥,你画的图也太恶心了吧,搞得我没有看的欲望。晚上抽空再看。想了解和深入的办法,就是我们自已去实现一个weibo,搭一下他们的架构。然后再回头看他们那些理论和谈话。
+1
++1
++9
看文章就知道图片会被开刀,++++1