如何使用拉模式设计信息流系统?
所谓拉模式,指的是用户自行获取其关注的所有人的微博,并按照发布时间的倒序进行排序和整合,从而生成信息流数据的方法。在设计微博信息流系统时,会发现用户的收件箱不再必要,因为信息流数据不再源自收件箱,而是来自发件箱。发件箱中包含了用户关注的所有人数据的整合。因此,用户在发布微博时只需将其写入自己的发件箱,而不再需要将其推送给粉丝的收件箱。这意味着在获取信息流时,需要查询发件箱的数据
这个逻辑我还用 SQL 的形式直观地表达出来,方便你理解。假设用户 A 关注了用户 B、C、D,那么当用户 B 发送一条微博的时候,他会执行这样的操作:
insert into outbox(userId, feedId, create_time) values("B", $feedId, $current_time); //写入B的发件箱
当用户 A 想要获取他的信息流的时候,就要聚合 B、C、D 三个用户收件箱的内容了:
select feedId from outbox where userId in (select userId from follower where fanId = "A") order by create_time desc
确实,拉模式相较于推模式具有明显的优势。首先,它解决了推送延迟的问题。在拉模式下,大 V 发微博时不再需要将消息推送到每个粉丝的收件箱,因此消除了推送延迟。其次,存储成本大幅降低。
在推模式下,每条微博都需要被复制并写入到每个粉丝的收件箱,而在拉模式下,只需保留发件箱,无需复制微博数据,从而降低了存储成本。最后,拉模式具有更好的功能扩展性。例如,如果微博增加了分组功能,用户想将关注的 A 和 B 分成一个单独的组,那么 A 和 B 发布的微博就形成了一个新的信息流。在拉模式下,只需查询该分组下所有用户(即 A 和 B),然后查询这些用户的发件箱,按时间倒序重新排序聚合即可实现这个信息流。
List uids = getFromGroup(groupId); //获取分组下的所有用户
Long ids = new ArrayList();
for(Long id : uids) {
ids.add(getOutboxByUid(id)); //获取发件箱的内容id列表
}
return merge(ids); //合并排序所有的id
对于拉模式而言,尽管在业务上关注数有上限,但它并非完美无缺的方案。下面是针对拉模式可能存在的问题的优化建议:
查询和聚合成本高: 在拉模式下,需要对多个发件箱的数据进行查询和聚合,这可能会导致成本较高。针对这个问题,可以利用缓存来优化。根据用户浏览信息流的特点,可以只缓存最近一段时间内的微博 ID,而不是所有用户的所有微博。比如,仅缓存每个用户最近几天内发布的微博 ID。这样,可以减少缓存的存储成本,并在查询时从多个缓存节点并行获取数据,以加快查询速度。
缓存节点带宽成本高: 缓存节点的带宽成本可能会很高,特别是在高流量情况下。针对这个问题,可以采取一些优化措施。例如,可以考虑对缓存数据进行压缩,减少数据传输量,从而降低带宽消耗。此外,可以使用更高带宽的网络设备或增加缓存节点数量来提升系统的带宽处理能力。
推拉结合的方案是怎样的?
这个方案的确是一个有效的解决方案,可以实现大 V 用户微博推送的精准化,以及活跃用户的识别和管理。以下是方案中关键点的总结和潜在的实施方法:
大 V 用户识别: 以粉丝数为判断标准是合理的方法,超过一定数量的粉丝可被视为大 V 用户。这个阈值可以根据实际情况进行调整。一旦识别出大 V 用户,系统就可以将他们作为特殊对象来处理。
活跃用户标记: 活跃用户的标记是方案的关键。可以通过记录用户最近几天内的操作行为来判断其活跃状态,如刷新信息流、发布微博、转发评论、点赞等。这些操作可以作为活跃用户的判断依据。
活跃粉丝列表管理: 对于大 V 用户,需要维护一个活跃粉丝列表。这个列表应该是定长的,当一个用户从不活跃变为活跃时,将其加入到相关大 V 用户的活跃粉丝列表中。当列表长度超过设定值时,可以采取先进先出的策略,移除最早加入的粉丝,以保持列表的有效性。
微博推送和收件箱更新: 对于活跃粉丝,实时推送大 V 用户的微博;对于不活跃粉丝或不在大 V 用户的活跃粉丝列表中的用户,将大 V 用户的微博异步插入到其收件箱中,以保证其信息流数据的完整性。
图片
推拉结合的方式可以在一定程度上弥补推模式的缺陷,但也带来了额外的维护成本。随着粉丝数量的增加,活跃粉丝列表的维护和推送延迟都会成为系统的瓶颈,这时候转换为拉模式可能会更为合适。
在粉丝数量较大的情况下,拉模式相对于推模式更具可扩展性和效率。拉模式不需要维护活跃粉丝列表,也不需要实时判断用户的在线状态,因此可以减少系统的维护成本和推送延迟。同时,拉模式也更适合应对高流量的情况,因为它不需要频繁地向大量用户推送消息,而是由用户自行拉取所关注用户的微博信息,减轻了系统的压力。
因此,在粉丝数量较大、流量不断增加的情况下,将推拉结合的方式转换为纯粹的拉模式可能会更好地支撑业务的发展,并提供更稳定、高效的服务。
总结:
在拉模式下,我们只需要保存用户的发件箱,用户的信息流是通过聚合关注者发件箱数据来实现的;
拉模式会有比较大的聚合成本,缓存节点也会存在带宽的瓶颈,所以我们可以通过一些权衡策略尽量减少获取数据的大小,以及部署缓存副本的方式来抗并发;
推拉结合的模式核心是只推送活跃的粉丝用户,需要维护用户的在线状态以及活跃粉丝的列表,所以需要增加多余的空间成本来存储,这个你需要来权衡。拉