公众号
新闻
娱乐
游戏
科技
搞笑
情感
美女
提交微信
微信号
地区微信号
微商卖货
微信营销
微信福利
提交微信群
微信文章
推荐
搞笑
生活
娱乐
娱乐
微信帮助
微信网页版
微信下载
微信公众平台
微信编辑器
微信导航WeiXin
公众号首页
精彩微信
提交微信公众号

微信朋友圈好友动态的实现

  • 2016-09-09 10:21:42
  • 一起加入96微信网(www.96weixin.com)微信导航平台,快速开展微信推广获取更多用户关注。

    我们现在好多软件都有一个类似朋友圈的功能:微博、微信、QQ…… 只要涉及到好友、粉丝这样的app或者是网站,一定有这样的一个功能。那这个功能是怎么样来实现的呢?

    1、基础逻辑

    如果你有N个好友,当他们其中有K个人发出了新的信息,你就可以看到按时间倒序的排列的动态。

    微信朋友圈好友动态的实现

    有些时候,还会根据业务的要求,将某些动态信息进行合并,比如:某几个人都回复了同一个贴子,就可以合并为,“xx1, xx2, xx3都回复了yyy发的贴子《老王真帅》”。这样就使得动态消息看起来不是那么冗长繁杂。

    好了,基本逻辑描述了这么多,想必大家都已经心领神会。几个必要的点:

    A、好友间的关注关系:单向关注一般称为粉丝;双向关注一般称为好友。为描述简单,统一称之为好友的关注关系;

    B、好友产生动态:好友做了需要记录和展示的动作;

    C、动态的聚合:多个好友产生的动态需要合并后展示。

    2、实现的原理

    那具体怎么样实现呢?有几种方法,我们一一来介绍。

    A、推送到信箱。

    这个是最容易想到的实现方法。假设我有一个信箱,如果我的好友,每次发新的动态的时候,都将他们的动态放一份到我的信箱里。这样,我每次去信箱里看的时候,就能从上到下看完所有的好友动态。

    微信朋友圈好友动态的实现

    上图演示的就是有新动态的好友将新的动态推送到我的信箱。因为整个过程是信息产生者主动发送的过程,所以这种方式我们就叫做推(push),这是一种主动的行为。

    优点:

    那这种方式最明显的优点就是:

    a、逻辑简单。这个可以用非常简单的伪代码来表示。

    foreach (Follower f in followerList)

    {

    f.mailbox.add(myMsg);

    }

    b、新动态信息显示及时。在数据量不大的情况下,基本上可以做到实时或者是准实时。这边儿动态一发,那边就可以显示出来。

    不过这个方法的问题也比较明显。比如,有一个明星,他有上千万的粉丝,如果他发一个动态……就只能呵呵了。我们简单算一下,如果每个动态推送给好友的时间假定为1个毫秒,那么1000万条动态顺序推送的话,就需要1ms * 1000w = 1ws 约等于 3个小时。

    也就是说,我们的系统什么事情都不做,在保证效率足够高的情况下,将这条动态推送给这个明星的所有关注者,需要3个小时。也就是说,最后一个粉丝要动态发生后3个小时才能看到。这个时效明显就失去了动态这个产品的意义了。

    那对于这个算法,我们有什么改进的方法嘛?

    当然有(不然老王怎么往下讲呢,对不对)!既然串行(一条条的)推很慢,那我们就让推这个动作并行起来。因为推这个动作消耗主要在网络上,而对于推送的机器来讲,cpu消耗是很低的,所以我们可以通过增加线程的方式,来提高推送的并行度。比如,开10个线程来推,这样我们所花的时间是不是就接近于原来的1/10了呢?

    不过,如果有很多明星都同时发动态,我们的线程估计就要爆掉了。那又有解决方案没有呢?那肯定也是有的。既然这个地方会卡在同步的发送上,我们是否可以用异步的方式来推送呢?还记得分布式系统嘛?还记得我们的Message Queue嘛?我们就可以用这个系统来解决我们的问题。

    微信朋友圈好友动态的实现

    当某一个朋友发送了一个新的动态,我们就将这个动态放到一个入口的发送器里(Poster),这个发送器立刻将这个动态转发到传送的Message Queue(trans-mq)。trans-mq是多层级联,根据实际用户量来计算。最后一层的mq是用来做实际更新的(update-mq)。每一个负责一组用户的更新,将相关的动态塞到需要管理的那组用户的信箱里。

    比方一个update-mq管理100万用户,那么我们如果有1亿用户,就只需要100个这样的update-mq,可能就只需要一个trans-mq。当某一个明星有发送新动态的时候,他的1000万粉丝散落在这100个update-mq管理的群组中,每个群组平均就只有10w个粉丝。如果写入每个mailbox还是1个毫秒,那么10w个粉丝就只需要100秒(大概2分钟)。这样,我们就把一个需要几小时处理完成的工作,变成了需要1-2分钟需要做的工作。为什么呢?因为他们并行起来工作了!

    那是不是就完结了呢?并不是!如果发送的信息违反xx规定需要删除怎么办呢?有两种方式:

    a、同样的流程还需要走一遍:将删除操作推送到各个信箱;

    b、全局增加一个删除位,记录所有删除过动态:用户请求的时候,将动态id去这个删除系统里面查,看看是否有删除过。如果有,则过滤掉已经删除的动态。

    好了,以上就是推送到信箱这种方式的工作原理和优化,怎么样,看懂了嘛?

    B、用时再拉取

    这第二种方式呢,实际就是一种懒人模式(lazy mode)。他究竟有多懒呢?真的,很懒。如果你的好友发了动态,你永远不登录,这个动态就永远不会推送给你。只有你登录到动态页面,系统才会懒洋洋的把你的好友的动态抽取一遍。

    微信朋友圈好友动态的实现

    上图大体描述了这个动态获取的过程:

    a、用户进入到动态页面(比如:朋友圈);

    b、获取好友列表;

    c、把好友的动态按时间倒排并展示。

    大家注意到没有,整个过程中,用户已经没有了那个mailbox,取而代之的是动态的去拉取好友的信息。相对于之前聊的主动推送而言,这个就是一个被动的拉取过程。

    由于是这样的一个工作模式,所以他有他的优点:当我关注了多个大V的时候,这些大V发动态不再主动推送给我,所以就避免了上千万次的主动推送过程。转而是用户浏览的时候再去获取。这使得我们的系统不会因为大V发动态而变得忙碌。

    不过,如果我们的登录用户很多 && 他们都关注了很多其他用户,我们的系统就会有很大压力了:因为,他们要动态获取被关注者的信息并且做聚合。那我们有哪些办法做优化么?来看老王的才艺展示:

    a、限制关注的数量:大家可以看到,好多的动态系统一般都限制用户添加好友或者关注的数量。其中有一个原因就有可能是采用了这样拉取动态的手段。限制用户关注量以后,我们系统在合并的时候,就可以减少合并的数量,从而提升效率;

    b、为每个用户建立动态的缓存:我们可以给每个用户建立一个动态的cache,如果关注他的人取拉取他的动态,就不用每次都从磁盘(或者数据库)拉取,而直接从缓存中获取。从而提升拉取的速度;

    c、为聚合后的动态建立缓存:还是缓存方案,不过这次针对的不是产生动态的人,而是浏览动态的人。一旦拉取过一次以后,我们就将聚合过后的数据做一个缓存,下次再刷新的时候,就直接可以从缓存中获取(特别适合那种手不停的下拉刷新朋友圈的人~)

    d、建立时间更新表:这个是个什么东东?如果我关注了500个人,如果平均每个人有10个动态,那一次给我5000个动态,对于我来讲,我会疯掉……所以,其实从产品上讲,没有必要将所有被关注者的动态都获取来展示,对吧。比如,我们可以获取最近有更新的20个或者50个被关注者,将他们的动态拉取做展示,对于绝大多数情况就非常适用。那种长期不更新的人,也没必要看,对吧~ 所以,我们可以为每个被关注者建立一个最后更新时间表,然后获取动态前,先看看哪些最近有更新,然后只拉取这些有更新的用户的动态做合并排序就可以了。

    好了,动态用时方去拉,这种方法就差不多说到这儿。看懂了么?

    在具体设计这个系统的时候,最好是根据产品业务形态、用户的数据规模等等综合来判断和考虑。两种方式各有优缺点,实现的成本也因规模不同。

    a、如果规模小,用最简单的推就可以了;

    b、如果规模中等,用简单优化过后的拉也可以了;

    c、如果是规模比较大,可以适度考虑优化过后的推或者拉,甚至推拉结合。

    没有一个完美的架构,只有更适合业务的方案。所以,一切都取决于你的选择~

    0  发布

    微信群