一看就懂系列之 feed的php具体实现细节
2016-04-25 23:33
477 查看
前言
假设这样一种情景:某创业团队想弄一个社交类的产品,其中包含类似“好友动态”或者“广场动态”之类的东西。刚开始我也不知道这玩意儿原来有个亲切的称呼叫feed流,feed流肯定是用类似java这样的语言实现是更好的,但是如果团队主语言是php,又处于初期(用户100w以内),那么php又该怎么设计实现feed呢?站在巨人的肩膀上看feed
那么关于feed流,很多前辈也是做了分享,这里列出本人认为典型代表的两篇:1.新浪微博架构和FEED架构分析–人人架构paper0023新浪博客
2. 微博feed系统的推(push)模式和拉(pull)模式和时间分区拉模式架构探讨
关于以上两篇大神之作,既然是大神传授的都是大概的一个实现机制,并没有涉及到具体的实现细节,对于我等非大神同学,关注的还是实现细节。
来聊聊实现细节
推拉模式
这里再简单的聊下什么是推拉模式(非专业、比较白话文的描述):
推模式
就是“cbs同学”关注了“tfboys”,那么每当tfboys发送一个动态,后台就需要遍历tfboys的千万粉丝,往他们的feed的里面推送一条动态。
拉模式
拉模式和推模式相反,就是每当“cbs同学”主动去刷新动态页的时候,都会去遍历关注的人的动态,把最新的动态拉取聚合取出来。
but,不管是推还是拉模式都会导致一个问题:就是关注数量或者粉丝数量过多,导致遍历时间过长,怎么破?于是还有一种模式:
推拉模式
这是一种折中的解决方案,关于哪些推哪些拉也是有讲究的,主要分为两种:
1.关注少粉丝多的适合“拉模式”,关注多粉丝少的适合“推模式”。
2.发动态时候,在线的推,离线的拉。
解释:
1.方式一,主要是通过限定合理的阀值,避开遍历时间过长的问题。
2.方式二,主要是根据“重要程度”来决定是推还是拉,因为即使是“tfboys”这样粉丝很多的,发动态时候也不一定所有粉丝都在线,只推送给在线的粉丝,离线的粉丝上线后再去拉取就好了。
附一道题:
如何聚合
不管是推模式还是拉模式,只是解决了如何把握最好的动态推送时间点问题,不管怎么说,聚合feed流更是关键所在。
“cbs同学”关注了“tfboys”,当“tfboys”发布动态时候就将动态推进“cbs同学”的feed,可以使用redis的zset去实现,sort为time(记得以毫秒为时间戳,秒级在数据量达到一定程度后,会有读取不到的问题,比如以时间戳为分页页码),value为具体的动态 ID(为什么是ID呢,一方面是为了省空间,内容实体额外取,另一方面redis里面全部走ID,修改动态内容也需要修改一个地方),每个用户维护一个zset保存我发布的动态,一个zset保存我的feed动态,过期时间3~7天看情况而定。
如果采用推拉模式的方式一,就直接按照(假设粉丝阀值是10w)粉丝大于10w的不推送,需要粉丝刷新重新聚合才会看到新动态,小于10w的主动推送消息到粉丝的feed流。
如果采用推拉模式的方式二,需要维护一份在线列表,(如果用户量是百万级别,月活可能只有10%这样,可以考虑使用,月活用户太多的话,维护成本较高),为了防止用户挂后台导致被判断为离线状态,所以最好是1~3小时未操作或者离线时间不大于3小时的,都当做在线处理,反正这个看情况定。
ps:很多app都是有限制关注上限的,所以对于关注数过多的问题基本被避免了。
详细细节:
推 :将发生的动态id,以及用户id,异步放到队列中去,由队列取出粉丝id,进而取出feed流的缓存,直接加一条就好啦~
拉 :对于拉的话,想看新动态主要看的还是聚合速度了,但是有时候会拉很久就麻烦了,有个优化的小技巧,同时开一个异步队列去异步的拉在线的人的feed流,拉取过程其实就是把自己最后一条Feed的时间戳取出,去遍历关注的人的feed,将大于该时间的ID全部拉取回来。用户进入APP后,刷新即可看到最新操作。
feed太长怎么办
可以这么处理:可以设置单个人的feed长度为一个限定的值(比如500),在app里面就相当于50页了,后面的数据取数据库就好,一般来说只有用户第一次看某个人动态,或者第一次用app,才会看到很后面,这种场景出现情况是比较少的。一般看过了就不会再看了,至于关注量很大的用户,feed动态肯定特别多,怎么办?首先这类用户八成是僵尸账号,不会去消费内容,即使不是僵尸账号,去消费内容,这么大的内容量即使后面走的是数据库,多等一会儿也是可以接受的。主要是情况少。
feed太占内容啦~
前面有提到feed的key需要设置过期值是有原因的。1.防止feed占的内存只增不减。
2.一个用户3~7天不打开APP,可能已经对APP失去兴趣了,打开几率很小,或者已经被卸载了,没有存在的意义了。
3.3~7天没登录,要是关注的人多,要拉的动态也不少,那么这时候去遍历其实拉取量很大,那么还不如直接全部重新拉一边或者拉取用户最后登陆时间后产出的数据。
ps:有参考自己公司项目大神的实现方案。
相关文章推荐
- 用jQuery来做简单的菜单栏的收缩
- leetcode-24. Swap Nodes in Pairs
- 剑指offer之编程(三)
- 一篇很不错的介绍jquery的上下文的文章
- 【转】JQuery插件ajaxFileUpload 异步上传文件(PHP版)
- Django报错expected string or buffer
- 【剑指offer-Java版】18树的子结构
- 【剑指offer-Java版】17合并两个排序链表
- 【剑指offer-Java版】16反转链表
- jquery对原生方法的使用
- nodejs原理
- javascript中的slice
- GIT 分支管理:分支管理策略、Bug分支、Feature分支
- [jQuery] 事件 方法
- 【剑指offer-Java版】15链表中倒数第K个结点
- 【剑指offer-Java版】14调整数组顺序使奇数位于偶数前面
- Javascript获取页面元素相对和绝对位置
- 【剑指offer-Java版】13O(1)时间删除链表结点
- JS实现全屏页面切换
- asp.net EF+MVC+Bootstrap 通用后台管理系统